{"record":{"id":"3bde2c17e93d8d46","repo":"argoproj/argo-workflows","slug":"failed-to-validate-claims-w","errorCode":null,"errorMessage":"failed to validate claims: %w","messagePattern":"failed to validate claims: %w","errorType":"exception","errorClass":null,"httpStatus":401,"severity":"error","filePath":"server/auth/sso/sso.go","lineNumber":438,"sourceCode":"func isValidFinalRedirectURL(redirect string) bool {\n\t// Copied from https://github.com/oauth2-proxy/oauth2-proxy/blob/ab448cf38e7c1f0740b3cc2448284775e39d9661/pkg/app/redirect/validator.go#L47\n\treturn strings.HasPrefix(redirect, \"/\") && !strings.HasPrefix(redirect, \"//\") && !invalidRedirectRegex.MatchString(redirect)\n}\n\n// authorize verifies a bearer token and pulls user information form the claims.\nfunc (s *sso) Authorize(authorization string) (*types.Claims, error) {\n\ttok, err := jwt.ParseEncrypted(strings.TrimPrefix(authorization, Prefix), []jose.KeyAlgorithm{jose.DIRECT}, []jose.ContentEncryption{jose.A256GCM})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse encrypted token: %w\", err)\n\t}\n\n\tc := &types.Claims{}\n\tif err := tok.Claims(s.encryptionKey, c); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decrypt token: %w\", err)\n\t}\n\n\tif err := c.Validate(jwt.Expected{Issuer: issuer}); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to validate claims: %w\", err)\n\t}\n\treturn c, nil\n}\n\nfunc (s *sso) getRedirectURL(r *http.Request) string {\n\tif s.config.RedirectURL != \"\" {\n\t\treturn s.config.RedirectURL\n\t}\n\n\tproto := \"http\"\n\n\tif r.URL.Scheme != \"\" {\n\t\tproto = r.URL.Scheme\n\t} else if s.secure {\n\t\tproto = \"https\"\n\t}\n\n\treturn fmt.Sprintf(\"%s://%s%soauth2/callback\", proto, r.Host, s.baseHRef)","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/sso/sso.go#L420-L456","documentation":"The token decrypted successfully, but the claims failed validation against jwt.Expected{Issuer}: the `iss` claim does not match the configured OIDC issuer (or expiry/audience checks fail per Claims.Validate). Argo treats the session as untrusted.","triggerScenarios":"c.Validate(jwt.Expected{Issuer: issuer}) fails because the token's `iss` differs from the configured `sso.issuer` (issuer URL changed, http vs https, trailing slash mismatch, alias mismatch), or the token is expired.","commonSituations":"Changing the OIDC issuer/alias config while old tokens are still presented; clock skew causing `exp` validation failures; provider behind a proxy exposing a different host than configured.","solutions":["Re-login to obtain a token issued by the currently configured issuer","Make sure `sso.issuer` matches the provider's actual issuer URL exactly (scheme, host, path)","Check for clock skew between argo-server and the IdP (NTP)","If using issuerAlias, keep it consistent with the value baked into existing tokens"],"exampleFix":"// before\nsso:\n  issuer: http://dex:5556/dex   # token iss is https://sso.example.com/dex\n// after\nsso:\n  issuer: https://sso.example.com/dex","handlingStrategy":"validation","validationCode":"// decode the JWE claims client-side and compare iss before calling\nu := jwt.Claims{}\ntok.Claims(key, &u)\nif u.Issuer != expectedIssuer { return errors.New(\"issuer mismatch, re-login\") }","typeGuard":null,"tryCatchPattern":"claims, err := sso.Authorize(auth)\nif err != nil {\n    return status.Error(codes.Unauthenticated, \"token rejected (issuer/expiry), re-login\")\n}","preventionTips":["Keep sso.issuer byte-exact with the IdP issuer (scheme/host/path)","Avoid changing issuer or alias without forcing re-login","Sync clocks with NTP to prevent exp failures","Test the full login flow after any SSO config change"],"tags":["jwt","claims-validation","issuer","sso"],"backgroundTag":"jwt-issuer-mismatch","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}