{"record":{"id":"7e101421a81ce4c6","repo":"googleapis/mcp-toolbox","slug":"failed-to-parse-and-verify-jwt-token-w","errorCode":null,"errorMessage":"failed to parse and verify JWT token: %w","messagePattern":"failed to parse and verify JWT token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/generic/generic.go","lineNumber":233,"sourceCode":"func (a AuthService) GetAuthorizationServer() string {\n\treturn a.AuthorizationServer\n}\n\n// Verifies generic JWT access token inside the Authorization header\nfunc (a AuthService) GetClaimsFromHeader(ctx context.Context, h http.Header) (map[string]any, error) {\n\tif a.McpEnabled {\n\t\treturn nil, nil\n\t}\n\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","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/auth/generic/generic.go#L215-L251","documentation":"GetClaimsFromHeader could not parse or cryptographically verify the JWT found in the request header. jwt.Parse with the JWKS-backed keyfunc failed — this covers malformed token structure, unsupported algorithms, missing/expired claims, or signature verification failure against the fetched JWKS. The underlying jwt/v5 error is wrapped for inspection.","triggerScenarios":"A request contains a non-empty <name>_token header whose value fails jwt.Parse: truncated/garbled token, signed with a key not in the JWKS, expired (exp in the past), used before nbf, or wrong algorithm in the header.","commonSituations":"Client sending an opaque token or a token from a different issuer into the <name>_token header; keys rotated on the auth server before JWKS refresh; clock skew making tokens appear expired; client pasting the token with extra whitespace.","solutions":["Decode the token at jwt.io and check header/alg, exp, and signature match the provider's JWKS","Confirm the client fetches its token from the same authorizationServer configured in toolbox","Request a fresh token — expired tokens fail verification","Check for clock skew between toolbox host and auth server","Trim whitespace and ensure the full three-part token is sent in the header"],"exampleFix":"// before (client sends wrong token type)\nhttp.setRequestHeader(\"myauth_token\", opaqueSessionId)\n// after\nhttp.setRequestHeader(\"myauth_token\", jwtAccessToken)","handlingStrategy":"try-catch","validationCode":"parts := strings.Split(tokenString, \".\")\nif len(parts) != 3 {\n    return fmt.Errorf(\"token is not a three-part JWT\")\n}\n// client-side: also check exp before sending\nclaims := decodePayload(parts[1])\nif exp, ok := claims[\"exp\"].(float64); ok && time.Now().Unix64() > int64(exp) {\n    return fmt.Errorf(\"token already expired; fetch a new one\")\n}","typeGuard":null,"tryCatchPattern":"claims, err := authSvc.GetClaimsFromHeader(ctx, header)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse and verify JWT token\") {\n        // reject request with 401; optionally check errors.As for jwt/v5 error types:\n        var vErr *jwt.ValidationError\n        if errors.As(err, &vErr) && vErr.Errors&jwt.ValidationErrorExpired != 0 {\n            // hint client to refresh token\n        }\n        return nil, http.StatusUnauthorized\n    }\n    return nil, http.StatusInternalServerError\n}","preventionTips":["Ensure clients send the JWT (not an opaque token) in the <name>_token header","Refresh tokens proactively before exp","Keep the auth server's key rotation aligned with JWKS refresh intervals","Trim whitespace around the header value"],"tags":["go","jwt","auth","security"],"backgroundTag":"jwt-verification-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}