Summary
Add Google OAuth as a login method for the Codeoid web UI. The daemon-side infrastructure is almost entirely implemented — the main remaining work is the web UI login button and confirming ZeroID's support for the auth-code exchange.
Current state (what's already built)
| Component |
Status |
| `GoogleOAuthProvider` in `identity-provider.ts` |
✅ Complete — exchanges Google code for verified user |
| `OAuthHandler` in `oauth.ts` |
✅ Complete — full OAuth 2.0 + PKCE flow |
| Server routing in `server.ts` |
✅ Complete — `/auth/authorize`, `/auth/idp-callback`, `/auth/callback`, `/auth/token` all wired |
| `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` env vars |
✅ Read in `server.ts`, switches from `LocalProvider` → `GoogleOAuthProvider` |
| Web UI "Sign in with Google" button |
❌ Missing |
| ZeroID auth-code grant confirmation |
❓ Needs verification with AuthN team |
Auth flow (already implemented daemon-side)
1. User clicks "Sign in with Google" in web UI
2. Browser → GET /auth/authorize?client_id=codeoid&code_challenge=<PKCE>
3. Daemon → 302 to https://accounts.google.com/o/oauth2/v2/auth
4. Google verifies user → 302 to /auth/idp-callback?code=<google-code>
5. Daemon exchanges with Google, gets verified user (sub, email, name)
6. Daemon mints HS256 auth code JWT signed with shared hmac_secret
7. 302 → /auth/callback?code=<auth-code>
8. Browser POSTs code + PKCE verifier to /auth/token
9. Daemon proxies to ZeroID /oauth2/token (authorization_code grant)
10. ZeroID validates HS256 auth code → returns RS256 access token
11. Web UI stores token, connects to daemon WebSocket ✅
What needs to be done
1. Web UI — "Sign in with Google" button (web/src/components/SignIn.tsx)
Add a button that generates a PKCE pair, stores the verifier in sessionStorage, then redirects to /auth/authorize. The existing /auth/callback page already handles the browser-side token exchange.
2. Config — move Google credentials through config schema
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are currently read directly from process.env in server.ts. They should be part of the config schema in config.ts like the other OAuth fields.
3. ZeroID — confirm auth-code grant support
The flow relies on ZeroID accepting grant_type=authorization_code with HS256 auth codes minted by codeoid (validated via the shared hmac_secret). Confirm with the AuthN team that highflame-authn supports this and document the required ZeroID-side config.
4. CLI — codeoid login --google (nice-to-have)
Opens the system browser to /auth/authorize, listens on a local redirect URI, persists the token.
Why this matters
This is a prerequisite for the planned mobile app — the mobile UX is designed around OAuth rather than manual API-key entry.
Summary
Add Google OAuth as a login method for the Codeoid web UI. The daemon-side infrastructure is almost entirely implemented — the main remaining work is the web UI login button and confirming ZeroID's support for the auth-code exchange.
Current state (what's already built)
Auth flow (already implemented daemon-side)
What needs to be done
1. Web UI — "Sign in with Google" button (
web/src/components/SignIn.tsx)Add a button that generates a PKCE pair, stores the verifier in
sessionStorage, then redirects to/auth/authorize. The existing/auth/callbackpage already handles the browser-side token exchange.2. Config — move Google credentials through config schema
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETare currently read directly fromprocess.envinserver.ts. They should be part of the config schema inconfig.tslike the other OAuth fields.3. ZeroID — confirm auth-code grant support
The flow relies on ZeroID accepting
grant_type=authorization_codewith HS256 auth codes minted by codeoid (validated via the sharedhmac_secret). Confirm with the AuthN team thathighflame-authnsupports this and document the required ZeroID-side config.4. CLI —
codeoid login --google(nice-to-have)Opens the system browser to
/auth/authorize, listens on a local redirect URI, persists the token.Why this matters
This is a prerequisite for the planned mobile app — the mobile UX is designed around OAuth rather than manual API-key entry.