- 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>
3.4 KiB
3.4 KiB
Quickstart: Google OAuth Authentication
Feature: 001-google-oauth-auth Date: 2026-01-29
Prerequisites
-
Google Cloud Console Setup
- Create a project at https://console.cloud.google.com
- Enable "Google+ API" or "Google Identity" API
- Configure OAuth consent screen (External, if not Google Workspace)
- Create OAuth 2.0 credentials (Web application type)
- Add authorized redirect URI:
http://localhost:3000/api/auth/google/callback
-
Environment Variables Add to
backend/.env:# Google OAuth GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret GOOGLE_CALLBACK_URL=http://localhost:3000/api/auth/google/callback # JWT Configuration JWT_SECRET=your-secure-random-secret-min-32-chars JWT_ACCESS_EXPIRATION=15m JWT_REFRESH_EXPIRATION=7d # Frontend URL (for redirects) FRONTEND_URL=http://localhost:5173
Installation
Backend Dependencies
cd backend
npm install @nestjs/passport @nestjs/jwt passport passport-google-oauth20 bcrypt
npm install -D @types/passport-google-oauth20 @types/bcrypt
Frontend Dependencies
No additional dependencies required. Uses existing:
- react-router-dom (routing)
- zustand (auth state)
- axios (API calls)
- shadcn/ui (UI components)
Database Migration
Create and run migration for new tables:
cd backend
npm run typeorm:generate -- -n CreateAuthTables
npm run typeorm:run
Tables created:
users(id, googleId, email, displayName, avatarUrl, createdAt, lastLoginAt)refresh_tokens(id, userId, token, expiresAt, createdAt, revokedAt)
Quick Test Flow
-
Start the backend:
cd backend && npm run start:dev -
Start the frontend:
cd frontend && npm run dev -
Test OAuth flow:
- Navigate to
http://localhost:5173/tool - Should redirect to login page
- Click "Sign in with Google"
- Complete Google consent
- Should redirect back to
/toolwith active session
- Navigate to
-
Verify session persistence:
- Refresh the page
- Should remain on
/toolwithout re-authenticating
-
Test sign out:
- Click user menu → Sign out
- Should redirect to login page
- Navigating to
/toolshould redirect to login
API Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/auth/google |
Initiate OAuth (browser redirect) |
| GET | /api/auth/google/callback |
OAuth callback handler |
| POST | /api/auth/refresh |
Refresh access token |
| GET | /api/auth/me |
Get current user (requires auth) |
| POST | /api/auth/logout |
Sign out (requires auth) |
Frontend Routes
| Path | Component | Protected |
|---|---|---|
/ |
LandingPage | No |
/login |
LoginPage | No |
/auth/callback |
AuthCallbackPage | No |
/tool |
ToolPage | Yes |
Troubleshooting
"redirect_uri_mismatch" error:
- Ensure callback URL in Google Console matches
GOOGLE_CALLBACK_URLexactly - Include protocol (http/https) and port
"Invalid token" after refresh:
- Check
JWT_SECRETis set and consistent - Verify refresh token cookie is being sent (check browser DevTools)
CORS errors:
- Ensure
FRONTEND_URLmatches exactly (including port) - Check
credentials: truein CORS config
Session not persisting:
- Verify
httpOnlycookie is set (check Application → Cookies in DevTools) - Check
sameSiteandsecuresettings match environment