feat(agentex-ui): OIDC login with server-side access token#351
feat(agentex-ui): OIDC login with server-side access token#351erichwoo-scale wants to merge 4 commits into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
bb896c7 to
c53787d
Compare
|
Addressed the Greptile P1s in
Rebased onto the updated base branch so the stack stays clean; the footer now renders Give Feedback → Account Picker → Log out (account picker placement lands in #350). |
6e749ef to
db8bec0
Compare
db8bec0 to
00d2195
Compare
8eb5b47 to
5f243a0
Compare
5d58576 to
054fad9
Compare
Add opt-in OIDC login on top of the BFF, keeping the access token out of the browser entirely. - NextAuth (generic OIDC provider) selected + enabled by a single env var, `AGENTEX_UI_AUTH_PROVIDER_ID`; disabled by default so non-auth deployments are unaffected (no SessionProvider mounts, no /api/auth/session calls). - The BFF attaches the access token as a Bearer server-side via `getToken` and drops the UI session cookie — the token never reaches client JS or the NextAuth session (which exposes only `error`). - Middleware auto-redirects unauthenticated requests to sign-in; a client guard re-auths on refresh failure; RP-initiated logout clears the IdP session. - Supports `client_secret_post` (dev) and `private_key_jwt` (prod). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address Greptile P1s. The refresh path and RP-initiated logout hardcoded Ory's `/oauth2/token` and `/oauth2/sessions/logout` paths, which 404 on non-Ory IdPs — silently forcing a re-auth loop (refresh) or a transparent re-login (logout). Resolve `token_endpoint` and `end_session_endpoint` from the issuer's `.well-known/openid-configuration` (cached per-process; failures not cached). No Ory-specific fallback: a missing token_endpoint fails the refresh cleanly (→ re-auth), and a missing end_session_endpoint means local-only logout rather than a guessed path. OneAuth (Ory Hydra) advertises both in discovery, and NextAuth already relies on the same document for sign-in. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A GET /api/auth/logout is reachable by a crafted cross-site navigation (SameSite=Lax sends the session cookie on top-level GET), letting an attacker end the user's IdP SSO session. Switch to POST (Lax cookies aren't sent on cross-site POST); the client POSTs and follows the returned RP-initiated logout URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t mode
Trim verbose/redundant comments across auth.ts, middleware, session-guard, layout and the
auth routes; drop provider-specific ("Ory") wording (endpoints come from discovery); rename
the non-auth "legacy mode" to "default mode". No behavior change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
054fad9 to
5cd4b21
Compare
|
I went through this myself and it looks good. I also had Claude do a review pass focused on regressions and open-source (auth-disabled) safety, and it surfaced 6 items worth a look. Default path is clean — verified with a real A few things to address on the auth-enabled path, roughly by severity:
|
declan-scale
left a comment
There was a problem hiding this comment.
Forgot to hit approve, just double check that first claude point and I think we should be good
Summary
Second of a 2-PR stack. Stacked on #350 — base is
feat/agentex-ui-account-picker, so this diff is auth-only (GitHub auto-retargets tomainonce #350 merges). The chart + deploy wiring lives in scaleapi/sgp#3961.Adds opt-in OIDC login on top of the BFF, keeping the access token out of the browser entirely.
AGENTEX_UI_AUTH_PROVIDER_ID; disabled by default so non-auth deployments are unaffected (noSessionProvider, no/api/auth/sessioncalls).Bearerserver-side viagetTokenand drops the UI session cookie — the token never reaches client JS or the NextAuth session (which exposes onlyerror).client_secret_post(dev) andprivate_key_jwt(prod).Why token-hidden (BFF) over exposing it on the session
Exposing the access token to client JS is contrary to the OAuth 2.0 for Browser-Based Apps BCP and would flag in security review. Keeping it server-side (the BFF attaches the Bearer) is the recommended pattern; the client only ever sees the same-origin proxy.
Demo
agentex-ui-oidc-auth.mov
Stack
AGENTEX_UI_AUTH_PROVIDER_ID,OIDC_ISSUER_URL, the client Secret viaenvFrom)Test plan
npm run typecheck/npm run lint— clean🤖 Generated with Claude Code