Phase 9: OAuth & Account Switching — Google + Authentik, multi-account

Backend:
- OAuth service with pluggable provider architecture (Google + Authentik)
- Generic authorize/callback endpoints for any provider
- Authentik OIDC integration (configurable base URL)
- hashed_password made nullable for OAuth-only users
- Migration 009: nullable password column
- /auth/switch endpoint returns full AuthResponse for account switching
- OAuth-only users get clear error on password login attempt
- UserResponse includes oauth_provider + avatar_url

Frontend:
- OAuth buttons on login form (Google + Authentik)
- OAuth callback handler (/auth/callback route)
- Multi-account auth store (accounts array, addAccount, switchTo, removeAccount)
- Account switcher dropdown in header (hover to see other accounts)
- "Add another account" option
- English + Russian translations

Config:
- GOOGLE_CLIENT_ID/SECRET/REDIRECT_URI
- AUTHENTIK_CLIENT_ID/SECRET/BASE_URL/REDIRECT_URI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 15:56:20 +03:00
parent d86d53f473
commit 5c651b7988
18 changed files with 436 additions and 33 deletions

View File

@@ -13,18 +13,18 @@ Allow users to authenticate via Google OAuth, and switch between multiple logged
## Tasks
- [ ] **9.1** Add `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI` to config.py + .env.example. Add `authlib` to pyproject.toml.
- [ ] **9.2** Create `backend/app/services/oauth_service.py`: register Google provider, get_authorization_url, handle_callback (fetch user info, create/link user, issue tokens).
- [ ] **9.3** Make `User.hashed_password` nullable (OAuth users have no password). Migration 008.
- [ ] **9.4** Add OAuth endpoints to auth.py: `GET /auth/oauth/{provider}/authorize`, `GET /auth/oauth/{provider}/callback`.
- [ ] **9.5** Add `POST /auth/switch` endpoint (accepts refresh token, returns full AuthResponse).
- [ ] **9.6** Update schemas: add oauth_provider to UserResponse.
- [ ] **9.7** Frontend: OAuth API functions, callback route component.
- [ ] **9.8** Frontend: OAuth buttons on login form ("Sign in with Google").
- [ ] **9.9** Frontend: extend auth-store with accounts array, switchAccount, addAccount.
- [ ] **9.10** Frontend: account switcher dropdown in header.
- [ ] **9.11** Update routes, i18n (en/ru).
- [ ] **9.12** Tests + verification.
- [x] **9.1** Add `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI` to config.py + .env.example. Add `authlib` to pyproject.toml.
- [x] **9.2** Create `backend/app/services/oauth_service.py`: register Google provider, get_authorization_url, handle_callback (fetch user info, create/link user, issue tokens).
- [x] **9.3** Make `User.hashed_password` nullable (OAuth users have no password). Migration 008.
- [x] **9.4** Add OAuth endpoints to auth.py: `GET /auth/oauth/{provider}/authorize`, `GET /auth/oauth/{provider}/callback`.
- [x] **9.5** Add `POST /auth/switch` endpoint (accepts refresh token, returns full AuthResponse).
- [x] **9.6** Update schemas: add oauth_provider to UserResponse.
- [x] **9.7** Frontend: OAuth API functions, callback route component.
- [x] **9.8** Frontend: OAuth buttons on login form ("Sign in with Google").
- [x] **9.9** Frontend: extend auth-store with accounts array, switchAccount, addAccount.
- [x] **9.10** Frontend: account switcher dropdown in header.
- [x] **9.11** Update routes, i18n (en/ru).
- [x] **9.12** Tests + verification.
---
@@ -41,4 +41,4 @@ Allow users to authenticate via Google OAuth, and switch between multiple logged
## Status
**NOT STARTED**
**COMPLETED**