Cover magic-link and SAML failures on auth error page

Browser auth callbacks still returned JSON or used one-off pages
for several refusal reasons. Route OIDC email verification,
magic-link, and SAML ACS failures through /auth/error with stable
error codes so users always see an explanation.

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:32:56 +00:00
committed by Cursor Agent
parent 68e78a2230
commit 318789ec38
8 changed files with 223 additions and 143 deletions

View File

@@ -32,7 +32,6 @@ import (
"go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/iam/saml"
"go.probo.inc/probo/pkg/saferedirect"
"go.probo.inc/probo/pkg/securecookie"
"go.probo.inc/probo/pkg/server/api/authn"
@@ -61,49 +60,15 @@ func (h *SAMLHandler) renderInternalServerError(w http.ResponseWriter) {
}
func (h *SAMLHandler) renderAssertionError(w http.ResponseWriter, r *http.Request, err error) {
if isClientSAMLError(err) {
httpserver.RenderError(w, http.StatusUnauthorized, err)
if code, ok := authErrorCodeFromSAML(err); ok {
h.logger.WarnCtx(r.Context(), "SAML login rejected", log.Error(err), log.String("error_code", code))
redirectAuthError(w, r, code)
return
}
h.logger.ErrorCtx(r.Context(), "cannot handle SAML assertion", log.Error(err))
httpserver.RenderError(w, http.StatusUnauthorized, errors.New("authentication failed"))
}
func isClientSAMLError(err error) bool {
if _, ok := errors.AsType[*saml.ErrSAMLConfigurationNotFound](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrSAMLDisabled](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrInvalidAssertion](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrReplayAttackDetected](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrEmailDomainMismatch](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrSAMLAutoSignupDisabled](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrUserInactive](err); ok {
return true
}
if _, ok := errors.AsType[*saml.ErrSAMLSubjectAlreadyInUse](err); ok {
return true
}
return false
redirectAuthError(w, r, authErrorAuthenticationFailed)
}
func (h *SAMLHandler) MetadataHandler(w http.ResponseWriter, r *http.Request) {