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

6.0 KiB

Implementation Plan: Google OAuth Authentication Screen

Branch: 001-google-oauth-auth | Date: 2026-01-29 | Spec: spec.md Input: Feature specification from /specs/001-google-oauth-auth/spec.md

Summary

Implement a Google OAuth 2.0 authentication screen that gates access to the ThumbPreview tool. Users must authenticate via Google before accessing protected routes (/tool). The implementation uses redirect-based OAuth flow with session persistence (7-day validity), preserving the user's originally requested destination after login. Backend handles OAuth callback and session management; frontend provides auth UI and route protection.

Technical Context

Language/Version: TypeScript 5.x (frontend + backend) Primary Dependencies:

  • Frontend: React 19.x, React Router 7.x, Zustand 5.x, @tanstack/react-query 5.x, shadcn/ui
  • Backend: NestJS 11.x, TypeORM 0.3.x, @nestjs/passport, passport-google-oauth20 Storage: PostgreSQL (users, sessions via TypeORM) Testing: Jest (backend), manual testing (frontend) Target Platform: Web (desktop + mobile browsers) Project Type: Web application (frontend + backend monorepo) Performance Goals: OAuth flow completion < 30 seconds, session validation < 100ms Constraints: Must work with existing Vite proxy setup, no .env in frontend Scale/Scope: Single user role, 7-day session validity with refresh

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Principle Status Notes
I. Tech Stack PASS Using React 19, NestJS 11, TypeORM, PostgreSQL per constitution
II. Architecture PASS Following monorepo structure: frontend/src/, backend/src/modules/
III. Styling & UI PASS Will use shadcn/ui Button, Card components with Tailwind
IV. Data Management PASS Zustand for auth state, React Query for user data, TypeORM for persistence
V. Development Practices PASS TypeScript strict mode, class-validator DTOs, ESLint

New Dependencies Required:

  • @nestjs/passport + passport + passport-google-oauth20 - OAuth authentication (NestJS official, MIT license)
  • @types/passport-google-oauth20 - TypeScript types

Justification: Passport.js is the de facto standard for Node.js authentication. @nestjs/passport provides official NestJS integration. These are well-maintained, MIT-licensed, and have minimal bundle impact (backend only).

Project Structure

Documentation (this feature)

specs/001-google-oauth-auth/
├── plan.md              # This file
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output
├── quickstart.md        # Phase 1 output
├── contracts/           # Phase 1 output
│   └── auth-api.yaml    # OpenAPI spec for auth endpoints
└── tasks.md             # Phase 2 output (/speckit.tasks command)

Source Code (repository root)

backend/
├── src/
│   ├── modules/
│   │   ├── auth/                    # NEW: Authentication module
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── google.strategy.ts
│   │   │   ├── jwt.strategy.ts
│   │   │   ├── guards/
│   │   │   │   ├── jwt-auth.guard.ts
│   │   │   │   └── google-auth.guard.ts
│   │   │   └── dto/
│   │   │       └── auth-response.dto.ts
│   │   ├── thumbnails/              # Existing
│   │   └── youtube/                 # Existing
│   └── entities/
│       ├── user.entity.ts           # NEW
│       ├── thumbnail.entity.ts      # Existing
│       └── youtube-cache.entity.ts  # Existing
└── tests/

frontend/
├── src/
│   ├── components/
│   │   ├── AuthGuard.tsx            # NEW: Route protection wrapper
│   │   └── UserMenu.tsx             # NEW: User avatar + sign out
│   ├── pages/
│   │   ├── LoginPage.tsx            # NEW: Auth screen
│   │   ├── AuthCallbackPage.tsx     # NEW: OAuth callback handler
│   │   ├── LandingPage.tsx          # Existing (public)
│   │   └── ToolPage.tsx             # Existing (protected)
│   ├── store/
│   │   └── authStore.ts             # NEW: Auth state (Zustand)
│   ├── api/
│   │   └── auth.ts                  # NEW: Auth API client
│   └── hooks/
│       └── useAuth.ts               # NEW: Auth hook
└── tests/

Structure Decision: Web application structure with frontend/backend separation per constitution. Auth module added to backend following NestJS module pattern. Frontend gets new pages for login flow and components for route protection.

Complexity Tracking

No constitution violations. All implementation follows established patterns.


Post-Design Constitution Re-Check

Re-validated after Phase 1 design completion.

Principle Status Validation
I. Tech Stack PASS Dependencies align: @nestjs/passport, passport-google-oauth20 (MIT, maintained)
II. Architecture PASS Auth module follows NestJS pattern, frontend follows components/pages/store structure
III. Styling & UI PASS LoginPage will use shadcn/ui Button, Card; Tailwind for layout
IV. Data Management PASS User entity uses UUID PK, Zustand for auth state, TypeORM for persistence
V. Development Practices PASS DTOs with class-validator, explicit TypeScript types, ESLint compliance

Phase 1 Artifacts Generated:

  • research.md - OAuth implementation patterns documented
  • data-model.md - User and RefreshToken entities defined
  • contracts/auth-api.yaml - OpenAPI spec for 5 auth endpoints
  • quickstart.md - Setup and testing guide
  • CLAUDE.md - Agent context updated with new technologies