- 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>
103 lines
3.1 KiB
Markdown
103 lines
3.1 KiB
Markdown
# 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`).
|