Surface invalid OIDC state on auth error page

Missing, expired, or reused OIDC state left users on a JSON error
or a generic failure. Map those cases to invalid_state so they get
a clear prompt to restart sign-in.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
This commit is contained in:
Bryan Frimin
2026-07-24 21:37:31 +00:00
committed by Cursor Agent
parent 318789ec38
commit b8e5d279a0
3 changed files with 18 additions and 1 deletions

View File

@@ -31,6 +31,7 @@ import (
const (
authErrorPersonalAccountNotAllowed = "personal_account_not_allowed"
authErrorEmailNotVerified = "email_not_verified"
authErrorInvalidState = "invalid_state"
authErrorAuthenticationFailed = "authentication_failed"
authErrorMagicLinkExpired = "magic_link_expired"
authErrorMagicLinkAlreadyUsed = "magic_link_already_used"

View File

@@ -125,7 +125,9 @@ func (h *OIDCHandler) CallbackHandler(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
if stateParam == "" || code == "" {
httpserver.RenderError(w, http.StatusBadRequest, errors.New("missing state or code"))
h.logger.WarnCtx(ctx, "OIDC callback missing state or code")
redirectAuthError(w, r, authErrorInvalidState)
return
}
@@ -145,6 +147,13 @@ func (h *OIDCHandler) CallbackHandler(w http.ResponseWriter, r *http.Request) {
return
}
if _, ok := errors.AsType[*oidc.ErrInvalidState](err); ok {
h.logger.WarnCtx(ctx, "OIDC login rejected: invalid or expired state")
redirectAuthError(w, r, authErrorInvalidState)
return
}
h.logger.ErrorCtx(ctx, "cannot handle OIDC callback", log.Error(err))
redirectAuthError(w, r, authErrorAuthenticationFailed)