Skip to content

fix(auth): recover OIDC login when callback arrives in a different br… - #205

Open
GabrielMSilva04 wants to merge 1 commit into
mainfrom
fix/oidc-cross-browser-state
Open

fix(auth): recover OIDC login when callback arrives in a different br…#205
GabrielMSilva04 wants to merge 1 commit into
mainfrom
fix/oidc-cross-browser-state

Conversation

@GabrielMSilva04

Copy link
Copy Markdown
Contributor

…owser

When a user clicks an Authentik verification email in Gmail/iOS Mail the callback opens in a new browser context with no oauth_state cookie, causing a 401 "session expired" — even though the verification succeeded.

Three fixes applied together:

Fix 1: Server-side PKCE state storage

  • New OAuthState table stores state/verifier/nonce/redirect per-request
  • oidc_login persists state to DB alongside the cookie
  • oidc_callback uses the cookie (fast path) and falls back to the DB row when the cookie is absent; DB failure is non-fatal (cookie still works)
  • cleanup_expired_oauth_states() runs at startup to prune stale rows
  • Alembic migration: b9e4c7f2a1d8

Fix 2: Distinct error code for the cross-browser case

  • _verify_and_pop_state_cookie raises detail="missing_state_cookie" only when both cookie and DB fallback fail
  • oidc_callback maps that detail to error=email_verified_relogin instead of the generic error=session
  • Login page renders email_verified_relogin as a green success notice ("Your account is verified! Sign in to continue.") with a "Sign in" button, since the email verification itself succeeded

Fix 3: Extend state cookie TTL from 10 min to 30 min

  • Covers slow email delivery without meaningful security impact
  • Same constant used for both the cookie max_age and DB expires_at

…owser

When a user clicks an Authentik verification email in Gmail/iOS Mail the
callback opens in a new browser context with no oauth_state cookie, causing
a 401 "session expired" — even though the verification succeeded.

Three fixes applied together:

Fix 1: Server-side PKCE state storage
- New OAuthState table stores state/verifier/nonce/redirect per-request
- oidc_login persists state to DB alongside the cookie
- oidc_callback uses the cookie (fast path) and falls back to the DB row
  when the cookie is absent; DB failure is non-fatal (cookie still works)
- cleanup_expired_oauth_states() runs at startup to prune stale rows
- Alembic migration: b9e4c7f2a1d8

Fix 2: Distinct error code for the cross-browser case
- _verify_and_pop_state_cookie raises detail="missing_state_cookie"
  only when both cookie and DB fallback fail
- oidc_callback maps that detail to error=email_verified_relogin instead
  of the generic error=session
- Login page renders email_verified_relogin as a green success notice
  ("Your account is verified! Sign in to continue.") with a "Sign in"
  button, since the email verification itself succeeded

Fix 3: Extend state cookie TTL from 10 min to 30 min
- Covers slow email delivery without meaningful security impact
- Same constant used for both the cookie max_age and DB expires_at
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
33.3% Coverage on New Code (required ≥ 50%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant