diff --git a/apps/console/src/pages/iam/auth/AuthErrorPage.tsx b/apps/console/src/pages/iam/auth/AuthErrorPage.tsx index 6a4a93e06..2ded2946a 100644 --- a/apps/console/src/pages/iam/auth/AuthErrorPage.tsx +++ b/apps/console/src/pages/iam/auth/AuthErrorPage.tsx @@ -46,6 +46,13 @@ function useAuthErrorContent(code: string | null): AuthErrorContent { "Your email address is not verified with the identity provider. Please verify it, then try signing in again.", ), }; + case "invalid_state": + return { + title: __("Sign-in session expired"), + description: __( + "This sign-in attempt is no longer valid. Please start again from the sign-in page.", + ), + }; case "magic_link_expired": return { title: __("Link Expired"), diff --git a/pkg/server/api/connect/v1/auth_error.go b/pkg/server/api/connect/v1/auth_error.go index b744ed0e8..cb7e781e6 100644 --- a/pkg/server/api/connect/v1/auth_error.go +++ b/pkg/server/api/connect/v1/auth_error.go @@ -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" diff --git a/pkg/server/api/connect/v1/oidc_handler.go b/pkg/server/api/connect/v1/oidc_handler.go index 3670cc43c..40a608ba1 100644 --- a/pkg/server/api/connect/v1/oidc_handler.go +++ b/pkg/server/api/connect/v1/oidc_handler.go @@ -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)