{"record":{"id":"ef6250a7c0f619df","repo":"googleapis/mcp-toolbox","slug":"invalid-jwt-claims-format","errorCode":null,"errorMessage":"invalid JWT claims format","messagePattern":"invalid JWT claims format","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/generic/generic.go","lineNumber":242,"sourceCode":"\n\ttokenString := h.Get(a.Name + \"_token\")\n\tif tokenString == \"\" {\n\t\treturn nil, nil\n\t}\n\n\t// Parse and verify the token signature\n\ttoken, err := jwt.Parse(tokenString, a.kf.Keyfunc)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse and verify JWT token: %w\", err)\n\t}\n\n\tif !token.Valid {\n\t\treturn nil, fmt.Errorf(\"invalid JWT token\")\n\t}\n\n\tclaims, ok := token.Claims.(jwt.MapClaims)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid JWT claims format\")\n\t}\n\n\t// Validate 'aud' (audience) claim\n\taud, err := claims.GetAudience()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not parse audience from token: %w\", err)\n\t}\n\n\tisAudValid := false\n\tfor _, audItem := range aud {\n\t\tif audItem == a.Audience {\n\t\t\tisAudValid = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif !isAudValid {\n\t\treturn nil, fmt.Errorf(\"audience validation failed: expected %s, got %v\", a.Audience, aud)","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/auth/generic/generic.go#L224-L260","documentation":"This error means the JWT was signature-valid, but its claims payload could not be represented as jwt.MapClaims (map[string]any). The generic auth service parses tokens with jwt.Parse and type-asserts token.Claims to MapClaims before validating the audience claim; if the assertion fails the claims are in an unexpected shape and validation aborts. This is a defensive check that rarely fires with well-formed JWTs from compliant issuers.","triggerScenarios":"GetClaimsFromHeader is called with an Authorization-style header '<Name>_token' whose value parses and verifies as a JWT, but token.Claims does not hold a jwt.MapClaims value — e.g. a token parsed into a custom claims struct, or a non-standard claims payload in the token string.","commonSituations":"Sending a non-JWT opaque string that some parser still marks valid, tokens whose claims are not a JSON object (e.g. a JSON array or string), or a misconfigured JWKS/keyfunc setup where a different parser produced the token object.","solutions":["Inspect the token payload at jwt.io and confirm claims are a flat JSON object (map), not an array or scalar.","Ensure the token is issued by your configured authorization server as a standard JWT, not an opaque token.","If you customized jwt.Parse with a custom claims type, align it with MapClaims or update the auth service accordingly."],"exampleFix":"// before: token with non-object claims payload\nAuthorization: eyJhbGciOi... (claims: [\"not\",\"an\",\"object\"])\n// after: reissue token with object claims\nAuthorization: eyJhbGciOi... (claims: {\"aud\":\"my-audience\",\"exp\":1893456000})","handlingStrategy":"type-guard","validationCode":"parts := strings.Split(tokenString, \".\")\nif len(parts) != 3 { return fmt.Errorf(\"not a JWT\") }\npayload, _ := base64.RawURLEncoding.DecodeString(parts[1])\nvar claims map[string]any\nif err := json.Unmarshal(payload, &claims); err != nil {\n    return fmt.Errorf(\"claims are not a JSON object: %w\", err)\n}","typeGuard":"func isMapClaims(t *jwt.Token) bool {\n    _, ok := t.Claims.(jwt.MapClaims)\n    return ok\n}","tryCatchPattern":"claims, err := svc.GetClaimsFromHeader(ctx, header)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid JWT claims format\") {\n        // reject token: non-object claims payload\n    }\n    return err\n}","preventionTips":["Decode the token payload at jwt.io before wiring it into clients","Ensure your IdP issues standard JSON-object claims","Never hand-craft JWTs with array/scalar payloads"],"tags":["jwt","auth","claims"],"backgroundTag":"invalid-jwt-claims-format","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}