# Research: Google OAuth Authentication **Feature**: 001-google-oauth-auth **Date**: 2026-01-29 ## 1. NestJS Passport Google OAuth Setup **Decision**: Use `@nestjs/passport` with `passport-google-oauth20` strategy **Rationale**: - Official NestJS integration provides decorator-based guards and strategies - `passport-google-oauth20` is the actively maintained Google OAuth package - Seamless integration with NestJS dependency injection and module system - Built-in validate method simplifies user profile handling **Alternatives Considered**: - `passport-google-oauth2`: Older package, less TypeScript support - Custom OAuth implementation: Too much boilerplate, harder to maintain ## 2. Authentication Strategy for SPAs **Decision**: Hybrid approach - JWT access tokens (short-lived, in-memory) + HttpOnly cookie refresh tokens (7-day) **Rationale**: - Access tokens in memory provide stateless, scalable API authentication - HttpOnly refresh tokens prevent XSS attacks while enabling token rotation - Best balance between security, UX, and distributed system requirements - Industry standard for modern SPAs **Alternatives Considered**: - Pure JWT (stateless): Can't invalidate tokens on logout/compromise - Pure sessions: Doesn't scale well, requires sticky sessions - localStorage for tokens: Vulnerable to XSS attacks ## 3. Token Storage in React **Decision**: Access tokens in Zustand store (memory), refresh tokens in HttpOnly cookies **Rationale**: - HttpOnly cookies are inaccessible to JavaScript, preventing XSS token theft - In-memory storage for short-lived access tokens (15-30 min) - CSRF protection via `sameSite: 'strict'` and CORS configuration - Silent refresh mechanism restores access token on page reload **Alternatives Considered**: - localStorage: Vulnerable to XSS attacks - sessionStorage: Data lost on tab close, still XSS vulnerable ## 4. React Router Protected Routes **Decision**: Layout-based protection using AuthGuard wrapper component with Navigate **Rationale**: - React Router v7 provides clean, declarative route protection - Easy to preserve intended destination via `location.state.from` - Simple loading state handling during auth check **Alternatives Considered**: - Higher-Order Component (HOC): More verbose in modern React - Route-level guards: Duplicates auth logic across routes ## 5. OAuth Redirect Flow Implementation **Decision**: Backend-initiated flow with frontend callback handler **Flow**: 1. Frontend links to `/api/auth/google` (backend initiates OAuth) 2. NestJS redirects to Google consent screen 3. Google redirects to `/api/auth/google/callback` 4. Backend validates tokens, creates/updates user, issues JWT 5. Backend redirects to frontend `/auth/callback?token=...` 6. Frontend stores token, clears URL, redirects to intended destination **Rationale**: - NestJS handles OAuth state management and token exchange securely - Supports TypeORM user creation/lookup with transaction safety - Token cleared from URL immediately for security **Alternatives Considered**: - Frontend-initiated PKCE flow: More complex state management - Popup-based flow: Poor UX on mobile, blocked by some browsers ## 6. Session Validity & Token Expiration **Decision**: - Access tokens: 15 minutes (short-lived for security) - Refresh tokens: 7 days (per spec assumptions) - Automatic token refresh via 401 interceptor in Axios **Rationale**: - Short access tokens limit exposure window if compromised - 7-day refresh aligns with spec requirements - Auto-refresh provides seamless UX ## Implementation Notes **CORS Configuration Required**: ``` origin: FRONTEND_URL credentials: true (allow cookies) ``` **Environment Variables Needed**: - GOOGLE_CLIENT_ID - GOOGLE_CLIENT_SECRET - GOOGLE_CALLBACK_URL - JWT_SECRET - JWT_ACCESS_EXPIRATION (15m) - JWT_REFRESH_EXPIRATION (7d) - FRONTEND_URL **TypeORM Indexes**: - Index `googleId` for OAuth lookups - Index `email` for user queries