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>
This commit is contained in:
126
specs/001-google-oauth-auth/plan.md
Normal file
126
specs/001-google-oauth-auth/plan.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Implementation Plan: Google OAuth Authentication Screen
|
||||
|
||||
**Branch**: `001-google-oauth-auth` | **Date**: 2026-01-29 | **Spec**: [spec.md](./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)
|
||||
|
||||
```text
|
||||
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)
|
||||
|
||||
```text
|
||||
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
|
||||
Reference in New Issue
Block a user