cloudflare/cloudflared · error
failed to retrieve JWT claims
Error message
failed to retrieve JWT claims
What it means
SignCert parses a JWT token and extracts its claims to build a certificate signing request. This error means the token itself parsed, but the claim payload inside could not be decoded into jwt.Claims via UnsafeClaimsWithoutVerification. The library wraps the underlying decode failure so the caller knows which phase of token processing failed.
Source
Thrown at sshgen/sshgen.go:101
}
return SignCert(token, string(pub))
}
func SignCert(token, pubKey string) (string, error) {
if token == "" {
return "", errors.New("invalid token")
}
parsedToken, err := jwt.ParseSigned(token, signatureAlgs)
if err != nil {
return "", errors.Wrap(err, "failed to parse JWT")
}
claims := jwt.Claims{}
err = parsedToken.UnsafeClaimsWithoutVerification(&claims)
if err != nil {
return "", errors.Wrap(err, "failed to retrieve JWT claims")
}
buf, err := json.Marshal(&signPayload{
PublicKey: pubKey,
JWT: token,
Issuer: claims.Issuer,
})
if err != nil {
return "", errors.Wrap(err, "failed to marshal signPayload")
}
var res *http.Response
if mockRequest != nil {
res, err = mockRequest(claims.Issuer+signEndpoint, "application/json", bytes.NewBuffer(buf))
} else {
client := http.Client{
Timeout: 10 * time.Second,
}
res, err = client.Post(claims.Issuer+signEndpoint, "application/json", bytes.NewBuffer(buf))View on GitHub (pinned to 2253eeeb25)
Solutions
- Verify the token is a real JWT with three dot-separated base64 segments and a JSON payload
- Decode the payload (e.g. base64 -d on the middle segment) and confirm the claims parse as JSON with the expected fields
- Re-run `cloudflared login` to obtain a fresh, well-formed token from Cloudflare
- Check for accidental whitespace/newlines or truncation when the token was copied into configuration
Example fix
// before
err = parsedToken.UnsafeClaimsWithoutVerification(&claims)
// after
if parsedToken == nil {
return "", errors.New("nil token")
}
if err = parsedToken.UnsafeClaimsWithoutVerification(&claims); err != nil {
return "", errors.Wrap(err, "failed to retrieve JWT claims")
} Defensive patterns
Strategy: validation
Validate before calling
// validate token shape before calling SignCert
parts := strings.Split(token, ".")
if len(parts) != 3 {
return errors.New("token is not a JWT (expected 3 segments)")
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return fmt.Errorf("JWT payload not base64url: %w", err)
}
var probe map[string]json.RawMessage
if err := json.Unmarshal(payload, &probe); err != nil {
return fmt.Errorf("JWT payload not valid JSON: %w", err)
} Try / catch
if _, err := SignCert(token, pubKey); err != nil {
if strings.Contains(err.Error(), "failed to retrieve JWT claims") {
// regenerate token via `cloudflared access login` and retry once
}
} Prevention
- Always obtain tokens via `cloudflared access login`/tokens API, never hand-edit them
- Validate the JWT shape (3 segments, JSON payload) before passing it in
- Avoid copying tokens through editors that may truncate or wrap lines
When it happens
Trigger: SignCert is called with a JWT whose decoded payload is not valid JSON or does not map to the expected claim fields (e.g. issuer not a string).
Common situations: Passing a corrupted or hand-edited token from cloudflared's config; passing a non-JWT opaque token; using a token whose claims contain unexpected types after an upstream format change.
Related errors
- invalid token
- failed to parse JWT
- aud array contains non-string elements
- aud field is not a string or an array of strings
- metadata JWT aud is empty
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/2870d2913d0bd38f.
Report an issue: GitHub.