Repository navigation
Conversation
Two hops of the /login/sso flow dropped the authorize request that oidcAuthzRequest exists to carry: - The Negotiate fallback. A browser that cannot answer the 401 challenge follows the page's meta-refresh, whose URL kept only redirect_uri. client_id, oidc, state, nonce and the PKCE challenge were lost, so the retry resolved the DEFAULT app: an app whose redirect_uri is only in its own allowlist got 400 "redirect_uri not allowed", and an OIDC attempt continued as a non-OIDC one. - The failure redirect. Every /login/sso failure called redirectToLoginError, which sends the browser to the client's redirect_uri with only ?error=<message>. That callback has no state, so OIDC clients reject it as a CSRF/state mismatch and the user never sees the real reason or gets a chance to use their password. The retry URL is now built from the same typed oidcAuthzRequest allowlist (plus oidc and sso_attempt), every value percent-encoded -- still no raw request text in the meta-refresh. Failures in an OIDC attempt go through renderOIDCLoginError, exactly like a failed password: back to SimpleAuth's authorize page with the error banner and the whole request, so the user can fall back to their password and the client still receives state, nonce and the PKCE challenge. Non-OIDC (hosted) flows keep redirecting to the app with ?error=, now for the right app. Tests fail on master and pass here: the retry keeps every authorize parameter, an OIDC failure returns to the authorize page with state and PKCE, a Kerberos-not-configured failure does the same, and the hosted flow still redirects an app-allowlisted redirect_uri with ?error=. Verified against a Samba AD DC behind nginx: a browser without Kerberos lands on the login page with the reason shown, and the AD password then completes the flow with code and state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When Kerberos SSO fails during an OIDC login, the browser ends up at the client's
redirect_uriwith?error=<message>and nostate. Every OIDC client treats a callback without itsstateas a CSRF attempt, so the user sees the client's state/CSRF error instead of the real reason, and never gets the chance to fall back to their AD password. A failed password attempt behaves correctly: it returns to SimpleAuth's login page with the whole request (H13).This is the follow-up named in #72. The two PRs touch different functions and merge cleanly in either order.
Two hops dropped the authorize request
oidcAuthzRequestdocuments the Kerberos SSO link as a hop that must carry the request. The way back out of/login/ssodid not:redirect_uri.client_id,oidc,state,nonceand the PKCE challenge were lost, so the retry resolved the default app:redirect_uriis only in its own allowlist got a dead-end400 redirect_uri not allowed;handleSSOLogincalledredirectToLoginError, which bounces to the client'sredirect_uri?error=…withoutstate.Change
oidcAuthzRequestallowlist, plusoidcandsso_attempt. Every value is percent-encoded byurl.Values.Encode, so the meta-refresh still contains no raw request text, and the existinghtml.EscapeStringstays as defence in depth.ssoLoginErrorroutes failures. An OIDC attempt (oidc=1) goes throughrenderOIDCLoginError, exactly like a failed password: back to SimpleAuth's authorize page with the error banner and the whole request. The__sso_attemptedcookie and the error banner already stop auto-SSO from looping. Non-OIDC (hosted) flows keepredirectToLoginErrorand its?error=redirect, now for the right app.Verification
Unit tests (
sso_failure_test.go). All four fail on master and pass here:oidcandsso_attempt=1;state,nonceand PKCE, never to the client's callback;redirect_uriwith?error=. Before, it got 400 from the default app.The existing OIDC/PKCE/H13 tests are unchanged and pass. The full
go test ./...is green, andgo vetandgofmtare clean.End to end: a Samba AD DC behind nginx with TLS, browser flows driven with one cookie jar:
?error=SSO authentication failed…, no statecode+state?error=Access denied…, no statecode+stateAssignment is still enforced where it was: a code issued after the password fallback to an unassigned user is refused at the token endpoint (
issueOIDCTokens→resolveTokenRoles→403 access_denied).🤖 Generated with Claude Code