{"record":{"id":"e6628a7dc15aed93","repo":"argoproj/argo-workflows","slug":"failed-to-parse-encrypted-token-w","errorCode":null,"errorMessage":"failed to parse encrypted token: %w","messagePattern":"failed to parse encrypted token: %w","errorType":"exception","errorClass":null,"httpStatus":401,"severity":"error","filePath":"server/auth/sso/sso.go","lineNumber":429,"sourceCode":"// It's not sufficient to only refer to RFC3986 for this validation logic\n// because modern browsers will convert back slashes (\\) to forward slashes (/)\n// and will interprete percent-encoded bytes.\n//\n// We used to use absolute redirect URLs and would validate the scheme and host\n// match the request scheme and host, but this led to problems when Argo is\n// behind a TLS termination proxy, since the redirect URL would have the scheme\n// \"https\" while the request scheme would be \"http\"\n// (see https://github.com/argoproj/argo-workflows/issues/13031).\nfunc 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","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/sso/sso.go#L411-L447","documentation":"sso.Authorize parses the incoming Authorization bearer cookie/token as a JWE encrypted token (direct key, A256GCM). If jose.ParseEncrypted fails — the token is malformed, not a JWE, truncated, or uses an unexpected algorithm — the request is rejected with this wrapped error.","triggerScenarios":"An HTTP request to the argo-server API carries an Authorization value that is not a valid JWE previously issued by the SSO callback; the token string was truncated/corrupted in transit or storage; a raw OIDC ID token (plain JWT, not encrypted) is presented instead of Argo's encrypted token.","commonSituations":"Users crafting the Authorization header by hand from their OIDC provider token; proxies or scripts stripping characters from the cookie; mixed versions where token format changed; testing with `argo` against a server whose cookie was issued under a different encryption key.","solutions":["Log in again via the SSO redirect flow to obtain a fresh encrypted token","Verify the Authorization header contains Argo's encrypted token (not a raw OIDC JWT or API key)","Ensure the token is passed intact (no truncation by proxy, curl quoting, or cookie size limits)","If tokens fail persistently, check that the server's token encryption key (argo-sso secret) has not changed/been deleted"],"exampleFix":"// before: sending raw OIDC token\n-H \"Authorization: <raw-id-token>\"\n// after: use token from Argo login (JWE), e.g. via CLI\nargo auth token   # returns the correct encrypted bearer token","handlingStrategy":"try-catch","validationCode":"if !strings.HasPrefix(auth, \"Bearer \") { return errors.New(\"missing bearer token\") }","typeGuard":null,"tryCatchPattern":"claims, err := sso.Authorize(auth)\nif err != nil {\n    return status.Error(codes.Unauthenticated, \"please re-authenticate via SSO\")\n}","preventionTips":["Always obtain tokens via the Argo login/callback flow or `argo auth token`","Never paste raw IdP JWTs into the Authorization header","Avoid proxies that mangle long cookies/headers","Re-login when switching clusters/environments"],"tags":["jwt","jwe","sso","authentication"],"backgroundTag":"malformed-token","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"}