feat: implement Google OAuth authentication
- Add Google OAuth 2.0 login flow with passport-google-oauth20 - Create User and RefreshToken entities for session management - Implement JWT access tokens (15min) + HttpOnly refresh cookies (7 days) - Add auth endpoints: /google, /google/callback, /refresh, /me, /logout - Create LoginPage with Google sign-in button (shadcn/ui) - Add AuthGuard for protected routes with redirect preservation - Implement silent token refresh on app mount - Add UserMenu component with avatar and sign-out Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
102
specs/001-google-oauth-auth/data-model.md
Normal file
102
specs/001-google-oauth-auth/data-model.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Data Model: Google OAuth Authentication
|
||||
|
||||
**Feature**: 001-google-oauth-auth
|
||||
**Date**: 2026-01-29
|
||||
|
||||
## Entities
|
||||
|
||||
### User
|
||||
|
||||
Represents an authenticated user in the system.
|
||||
|
||||
| Field | Type | Constraints | Description |
|
||||
|-------|------|-------------|-------------|
|
||||
| id | UUID | PK, auto-generated | Unique identifier |
|
||||
| googleId | string | UNIQUE, NOT NULL, indexed | Google account identifier |
|
||||
| email | string | UNIQUE, NOT NULL, indexed | User's email from Google |
|
||||
| displayName | string | NOT NULL | User's display name from Google |
|
||||
| avatarUrl | string | NULLABLE | Profile picture URL from Google |
|
||||
| createdAt | timestamp | NOT NULL, auto | Account creation timestamp |
|
||||
| lastLoginAt | timestamp | NOT NULL | Last successful login timestamp |
|
||||
|
||||
**Indexes**:
|
||||
- `idx_user_google_id` on `googleId` (OAuth lookup)
|
||||
- `idx_user_email` on `email` (user queries)
|
||||
|
||||
**Validation Rules**:
|
||||
- `googleId`: Non-empty string from Google profile
|
||||
- `email`: Valid email format (validated by Google)
|
||||
- `displayName`: Non-empty string, max 255 characters
|
||||
|
||||
### RefreshToken
|
||||
|
||||
Tracks issued refresh tokens for session management and revocation.
|
||||
|
||||
| Field | Type | Constraints | Description |
|
||||
|-------|------|-------------|-------------|
|
||||
| id | UUID | PK, auto-generated | Unique identifier |
|
||||
| userId | UUID | FK → User.id, NOT NULL | Associated user |
|
||||
| token | string | UNIQUE, NOT NULL, indexed | Hashed refresh token |
|
||||
| expiresAt | timestamp | NOT NULL | Token expiration time |
|
||||
| createdAt | timestamp | NOT NULL, auto | Token creation timestamp |
|
||||
| revokedAt | timestamp | NULLABLE | Revocation timestamp (soft delete) |
|
||||
|
||||
**Indexes**:
|
||||
- `idx_refresh_token_token` on `token` (token lookup)
|
||||
- `idx_refresh_token_user_id` on `userId` (user token queries)
|
||||
|
||||
**Validation Rules**:
|
||||
- `expiresAt`: Must be in the future when created
|
||||
- `token`: Hashed with bcrypt or similar before storage
|
||||
|
||||
**Lifecycle**:
|
||||
- Created: On successful OAuth login
|
||||
- Active: `revokedAt` is NULL and `expiresAt` > now
|
||||
- Revoked: When user logs out or token is rotated
|
||||
- Expired: `expiresAt` <= now (cleaned up periodically)
|
||||
|
||||
## Relationships
|
||||
|
||||
```
|
||||
User 1 ──────< RefreshToken
|
||||
(one-to-many)
|
||||
```
|
||||
|
||||
- One User can have multiple RefreshTokens (multiple devices/sessions)
|
||||
- When User is deleted, cascade delete all RefreshTokens
|
||||
|
||||
## State Transitions
|
||||
|
||||
### User Lifecycle
|
||||
|
||||
```
|
||||
[New] ──(first OAuth login)──> [Active]
|
||||
│
|
||||
(subsequent logins)
|
||||
↓
|
||||
[Active] (lastLoginAt updated)
|
||||
```
|
||||
|
||||
### RefreshToken Lifecycle
|
||||
|
||||
```
|
||||
[Created] ──(user logout)──> [Revoked]
|
||||
│
|
||||
├──(token refresh)──> [Rotated/New Created]
|
||||
│
|
||||
└──(time passes)──> [Expired]
|
||||
```
|
||||
|
||||
## Data Volume Assumptions
|
||||
|
||||
- Users: Expected < 10,000 initially
|
||||
- RefreshTokens: ~1-3 per user (multiple devices)
|
||||
- Token cleanup: Daily job to remove expired/revoked tokens older than 30 days
|
||||
|
||||
## Migration Notes
|
||||
|
||||
New tables required:
|
||||
1. `users` - Core user table
|
||||
2. `refresh_tokens` - Token tracking for session management
|
||||
|
||||
No modifications to existing tables (`thumbnails`, `youtube_cache`).
|
||||
Reference in New Issue
Block a user