OAuth Edition — Google Sign-In + API Key for MCP
| Concern | Password (JWT-only) | OAuth (Google) |
|---|---|---|
| Password storage | You manage bcrypt hashes | Google handles it |
| Password reset flow | You build it | Not needed |
| Email verification | You build it | Google verifies |
| Brute-force protection | You implement rate limiting | Google handles it |
| Account recovery | You build it | Google handles it |
| Initial setup | No external deps | Register Google Cloud app (~15 min) |
| Ongoing maintenance | High | Near zero |
http://100.103.206.4:8000/api/auth/callbackhttp://localhost:8000/api/auth/callback for local devFiles: app/db.py app/models.py
authlib handles the OAuth dance. python-jose for JWT signing. No bcrypt/passlib needed.
GET /api/auth/login — Redirects browser to Google consent screen
GET /api/auth/callback — Google redirects back here with auth code
GET /api/auth/me — Returns current user from JWT
Files: app/auth.py (new) app/main.py
The auth dependency accepts either a valid JWT or the X-API-Key header. This keeps the MCP server working without OAuth.
X-API-Key: {key} header to every request. No OAuth dance needed for machine-to-machine.authlib needs Starlette sessions to store the OAuth state parameter during the redirect flow. Add:
One-time migration that preserves all existing data:
Files: app/migrations/001_add_auth.py (new)
Every CRUD operation filters by the authenticated user:
Files: app/db.py app/main.py
| Route | Auth | Notes |
|---|---|---|
/health | Public | Health check |
/api/auth/login | Public | Initiates OAuth |
/api/auth/callback | Public | OAuth callback |
/api/auth/me | Protected | Current user profile |
/api/projects/* | Protected | User-scoped |
/api/visions/* | Protected | User-scoped |
/api/journal/* | Protected | User-scoped |
Files: app/tracking.py (new)
source="mcp" to distinguish Claude-initiated actionsAuto-prune logs older than 90 days. Run on app startup:
GET /api/me — full profile + statsPATCH /api/me — update display_name (email managed by Google)GET /api/me/stats — personal usage: projects created, journal streaks, active daysGET /api/me/sessions — list active refresh tokens (device, created)DELETE /api/me/sessions/{id} — revoke a tokenX-API-Key header to every request in MCP server configget_activity_summary — "What have I been working on?"get_recent_changes — Feed of what changed recentlyget_user_profile — Current user info and statsFiles: mcp_server/tools.py