Skip to content

fix(auth): recover organizations from userinfo when a refresh has no id token#14

Merged
coopbri merged 1 commit into
masterfrom
fix/getauth-org-userinfo-fallback
Jul 11, 2026
Merged

fix(auth): recover organizations from userinfo when a refresh has no id token#14
coopbri merged 1 commit into
masterfrom
fix/getauth-org-userinfo-fallback

Conversation

@coopbri

@coopbri coopbri commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Bug

getAuth reads org claims only from the ID token, but Gatekeeper issues an id_token only at login — not on the refresh-token grant. So once a session's access token refreshes (~hourly), organizations goes empty and every Omni dashboard (herald/backfeed/runa) shows "No workspaces yet" until the user re-logs in. (Same root as the sign-out id_token_hint gap.) Confirmed live on Herald.

Fix

Extract the existing userinfo hydration into a helper and also run it when the ID token is absent (or carries no org claim), recovering organizations from the OIDC UserInfo endpoint with the access token — the standard OIDC mechanism (Core §5.3), already used here for slim tokens.

Security / spec

  • Enforces OIDC Core §5.3.2: the userinfo sub MUST match the session subject before its claims are trusted; a mismatch is rejected (new test covers this).
  • ID-token verification is unchanged (still verified via JWKS when present).
  • Cached per-subject with the existing TTL, so it's not a per-request round-trip.

Testing

287 tests pass, incl. new no-id-token recovery and sub-mismatch rejection cases. tsc/biome/knip clean. Build diff isolated to build/auth (+ core barrel re-export); no build/react churn, no jsxDEV.

…id token

getAuth read the org claims only from the ID token, but Gatekeeper issues an
id_token only at login, not on the refresh-token grant. So once a session's
access token refreshed (~hourly), `organizations` went empty and every Omni
dashboard (herald/backfeed/runa) showed "No workspaces yet" until re-login.

Extract the userinfo hydration into a helper and also run it when the id token
is absent (or carried no org claim), recovering orgs from the OIDC UserInfo
endpoint with the access token. Per OIDC Core 5.3.2 the userinfo `sub` must
match the session subject before its claims are trusted; a mismatch is rejected.
Cached per subject (existing TTL) so it is not a per-request round-trip.

287 tests pass (incl. new no-id-token recovery + sub-mismatch rejection);
tsc/biome/knip clean. Build isolated to build/auth; no jsxDEV.
@coopbri coopbri merged commit 978ba23 into master Jul 11, 2026
4 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant