Files
Andre 130f35c4f8 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>
2026-01-29 13:05:18 -03:00

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`).