googleapis/mcp-toolbox · error
failed to parse and verify JWT token: %w
Error message
failed to parse and verify JWT token: %w
What it means
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.
Source
Thrown at internal/auth/generic/generic.go:233
func (a AuthService) GetAuthorizationServer() string {
return a.AuthorizationServer
}
// Verifies generic JWT access token inside the Authorization header
func (a AuthService) GetClaimsFromHeader(ctx context.Context, h http.Header) (map[string]any, error) {
if a.McpEnabled {
return nil, nil
}
tokenString := h.Get(a.Name + "_token")
if tokenString == "" {
return nil, nil
}
// Parse and verify the token signature
token, err := jwt.Parse(tokenString, a.kf.Keyfunc)
if err != nil {
return nil, fmt.Errorf("failed to parse and verify JWT token: %w", err)
}
if !token.Valid {
return nil, fmt.Errorf("invalid JWT token")
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return nil, fmt.Errorf("invalid JWT claims format")
}
// Validate 'aud' (audience) claim
aud, err := claims.GetAudience()
if err != nil {
return nil, fmt.Errorf("could not parse audience from token: %w", err)
}
isAudValid := falseView on GitHub (pinned to 8cc6e09de2)
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
Example fix
// before (client sends wrong token type)
http.setRequestHeader("myauth_token", opaqueSessionId)
// after
http.setRequestHeader("myauth_token", jwtAccessToken) Defensive patterns
Strategy: try-catch
Validate before calling
parts := strings.Split(tokenString, ".")
if len(parts) != 3 {
return fmt.Errorf("token is not a three-part JWT")
}
// client-side: also check exp before sending
claims := decodePayload(parts[1])
if exp, ok := claims["exp"].(float64); ok && time.Now().Unix64() > int64(exp) {
return fmt.Errorf("token already expired; fetch a new one")
} Try / catch
claims, err := authSvc.GetClaimsFromHeader(ctx, header)
if err != nil {
if strings.Contains(err.Error(), "failed to parse and verify JWT token") {
// reject request with 401; optionally check errors.As for jwt/v5 error types:
var vErr *jwt.ValidationError
if errors.As(err, &vErr) && vErr.Errors&jwt.ValidationErrorExpired != 0 {
// hint client to refresh token
}
return nil, http.StatusUnauthorized
}
return nil, http.StatusInternalServerError
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid JWT token
- google ID token verification failure: %w
- failed to create keyfunc from JWKS URL %s: %w
- invalid JWT claims format
- could not parse audience from token: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/7e101421a81ce4c6.
Report an issue: GitHub.