fix(oidc): gate authorize on a server-validated OP session (BUNYIP-53) #67
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/bunyip-53-logout-terminates-op-session"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
After the PMS-137 Option-B cutover, bunyip-api is the OIDC OP. The mokosh SPA logout drives the browser to the hub
/logout, yet the next/oauth2/authorizeimmediately re-authenticated the user and bounced back to/dashboardinstead of landing on/login(BUNYIP-53).Root cause:
/oauth2/authorizeauthenticated only off the stateless hubaccess_tokencookie and minted a brand-newop_sessionon every call, consulting no server-side session state.logoutrevoked theop_sessionsrows and cleared cookies, but authorize read none of that, so a surviving/replayedaccess_token(e.g. across the staginga8n.systems/api.a8n.systemscookie-domain split) kept minting codes. PMS-137 had deliberately made the hubaccess_tokendouble as the OP session viaCOOKIE_DOMAIN; that implicit reliance was the defect.Re-verified at runtime (token-replay against the local
just devstack): after a clean logout that cleared both cookies and revoked the op_sessions, replaying the pre-logoutaccess_tokenat/oauth2/authorizestill returned302 -> cb?code=....Fix
A real, server-validated OP session cookie:
op_sessionand sets an opaquebunyip_op_sessioncookie at every login event (password, 2FA, magic-link, invite accept, register, first-admin setup)./oauth2/authorizereads that cookie, validates it via the existingload_op_session, reuses the session (retiring the per-request create and itsTODO), and redirects to/loginwhen the session is absent, expired, or revoked. It no longer trusts the statelessaccess_token, so a stale token can no longer mint a code.logoutrevokes theop_sessionssynchronously (back-channel logout-token fan-out stays spawned) so an immediately-subsequent authorize finds no session;AuthCookies::clearalso deletesbunyip_op_session. The same revoke is applied toGET /v1/auth/logoutand/v1/auth/logout-allvia a shared helper.No schema change and no new sqlx queries (reuses
op_sessions,create_op_session,load_op_session,revoke_sessions_for_backchannel).Verification
just check-containergreen (fmt + clippy-D warnings+ workspace lib tests; only the pre-existing sqlx-postgres future-incompat warning).Runtime token-replay against the rebuilt
just dev-detachstack:bunyip_op_sessionalongside access/refreshcb?code=...(happy path)access_tokenafter logout/login(was: minted a code)bunyip_op_sessionafter logout/login(revoked server-side)/logincb?code=...(intact)Out of scope
AC2 (un-fixme the mokosh-server
auth-uiE2E, PMS-142) lives in the mokosh-server repo and follows after this lands and deploys to staging. Final staging re-verification of AC1 happens on the converged Option-B deploy.Refs BUNYIP-53.