Files
frontend/specs/001-google-oauth-auth/research.md
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

3.9 KiB

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