argoproj/argo-workflows · error
failed to decrypt token: %w
Error message
failed to decrypt token: %w
What it means
The token parsed as JWE, but decrypting its claims with the server's token encryption key (tok.Claims) failed. This means the token was encrypted with a different key (or corrupted). Argo rejects the request because claims cannot be trusted.
Source
Thrown at server/auth/sso/sso.go:434
// match the request scheme and host, but this led to problems when Argo is
// behind a TLS termination proxy, since the redirect URL would have the scheme
// "https" while the request scheme would be "http"
// (see https://github.com/argoproj/argo-workflows/issues/13031).
func isValidFinalRedirectURL(redirect string) bool {
// Copied from https://github.com/oauth2-proxy/oauth2-proxy/blob/ab448cf38e7c1f0740b3cc2448284775e39d9661/pkg/app/redirect/validator.go#L47
return strings.HasPrefix(redirect, "/") && !strings.HasPrefix(redirect, "//") && !invalidRedirectRegex.MatchString(redirect)
}
// authorize verifies a bearer token and pulls user information form the claims.
func (s *sso) Authorize(authorization string) (*types.Claims, error) {
tok, err := jwt.ParseEncrypted(strings.TrimPrefix(authorization, Prefix), []jose.KeyAlgorithm{jose.DIRECT}, []jose.ContentEncryption{jose.A256GCM})
if err != nil {
return nil, fmt.Errorf("failed to parse encrypted token: %w", err)
}
c := &types.Claims{}
if err := tok.Claims(s.encryptionKey, c); err != nil {
return nil, fmt.Errorf("failed to decrypt token: %w", err)
}
if err := c.Validate(jwt.Expected{Issuer: issuer}); err != nil {
return nil, fmt.Errorf("failed to validate claims: %w", err)
}
return c, nil
}
func (s *sso) getRedirectURL(r *http.Request) string {
if s.config.RedirectURL != "" {
return s.config.RedirectURL
}
proto := "http"
if r.URL.Scheme != "" {
proto = r.URL.Scheme
} else if s.secure {View on GitHub (pinned to 35bff19146)
Solutions
- Have users re-authenticate to get tokens encrypted with the current key
- Ensure all argo-server replicas share the same token encryption key from the same secret
- If the key was rotated, invalidate old sessions and force a fresh SSO login
- Verify secret name/key in the SSO config matches the actual k8s secret
Defensive patterns
Strategy: try-catch
Try / catch
claims, err := sso.Authorize(auth)
if err != nil {
// key mismatch/corruption: force re-login
return status.Error(codes.Unauthenticated, "session invalid, re-login")
} Prevention
- Keep the token encryption key stable; treat rotation as a session-breaking event
- Ensure all replicas mount the same secret
- Never copy tokens between environments
- Document key rotation runbooks for users
When it happens
Trigger: sso.Authorize receives a syntactically valid JWE whose content encryption key does not match s.encryptionKey — e.g. the argo-sso secret/token-encryption key was rotated or differs between server replicas, or a token from another cluster is presented.
Common situations: Rotating or recreating the `argo-workflows-sso` secret while users hold old cookies; multiple argo-server instances with mismatched keys (different namespace/secret per instance); copying tokens between dev/staging clusters.
Related errors
- failed to create JWT encrypter: %w
- failed to parse encrypted token: %w
- failed to validate claims: %w
- failed to list SSO RBAC service accounts: %w
- failed to marshall claims: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/fa1f4e302fe1fab8.
Report an issue: GitHub.