OpenNHP/opennhp · error
failed to parse token
Error message
failed to parse token: %w
What it means
VerifyJWT first parses the JWT with ParseUnverified solely to inspect the header; if the token string is malformed (bad base64, invalid JSON segments, wrong compact form), it returns 'failed to parse token: %w'. This is a pre-verification structural check before extracting the embedded JWK. The wrapped go-jose/jwt error names the exact defect.
Solutions
- Log/print the token structure: it must have exactly three dot-separated base64url segments.
- Fix the client to emit a valid ES256 JWT signed per the COSE/JWK-embedded scheme.
- Check for proxy or framework munging of the Authorization header (line folding, truncation).
- Ensure no whitespace/newlines are embedded in the token string.
- Decode each segment offline (e.g. `base64 -d` after padding) to find the malformed part.
Example fix
// client side: ensure compact JWS serialization, three base64url segments // before: sending raw key material token := base64.StdEncoding.EncodeToString(keyBytes) // after: produce a properly signed JWT token := jwt.NewWithClaims(jwt.SigningMethodES256, claims) s, _ := token.SignedString(privateKey)
Defensive patterns
Strategy: validation
Validate before calling
func looksLikeJWT(token string) bool {
parts := strings.Split(token, ".")
if len(parts) != 3 { return false }
for _, p := range parts {
if _, err := base64.RawURLEncoding.DecodeString(p); err != nil { return false }
}
return true
}
// call looksLikeJWT(token) before VerifyJWT Type guard
func isWellFormedJWS(s string) bool { return strings.Count(s, ".") == 2 && len(s) > 0 } Try / catch
token, err := VerifyJWT(rawToken)
if err != nil {
if strings.HasPrefix(err.Error(), "failed to parse token") {
// malformed token: return 400, ask client to re-issue
}
} Prevention
- Emit tokens only with a maintained JWT/JWS library.
- Never send opaque keys or session ids where a JWT is expected.
- Beware proxies truncating large Authorization headers.
- Use base64url (not standard base64) for all segments.
- Add client-side pre-validation of token shape before sending.
When it happens
Trigger: GetResource is called with an Authorization token that is not a well-formed three-part JWT: truncated token, non-base64url characters, malformed JSON in header/payload, empty string, or extra segments.
Common situations: Client sends a raw API key or an opaque session token instead of a JWT; token truncated by an intermediary (header size limits, proxy mangling); wrong encoding (standard base64 with padding instead of base64url); missing 'Bearer ' prefix handling leaving stray text.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- missing or invalid jwk in header
- unexpected signing method
- JWT signing key is not initialized
- resource not found
- failed to parse ztdo header
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/cf900875208c3476.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/server/kbs/resource/resource.go:216
return nil, nil, nil, err
}
iv = make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
return nil, nil, nil, err
}
ciphertext = gcm.Seal(nil, iv, plaintext, nil)
return ciphertext, iv, nil, nil
}
func VerifyJWT(tokenString string) (*jwt.Token, error) {
// First parse the token without verification to get the header
parser := jwt.NewParser()
unverifiedToken, _, err := parser.ParseUnverified(tokenString, jwt.MapClaims{})
if err != nil {
return nil, fmt.Errorf("failed to parse token: %w", err)
}
// Extract JWK from header
jwkHeader, ok := unverifiedToken.Header["jwk"].(map[string]any)
if !ok {
return nil, fmt.Errorf("missing or invalid jwk in header")
}
// Convert JWK back to ECDSA public key
xStr, ok := jwkHeader["x"].(string)
if !ok {
return nil, fmt.Errorf("missing x coordinate in jwk")
}
yStr, ok := jwkHeader["y"].(string)
if !ok {
return nil, fmt.Errorf("missing y coordinate in jwk")
}
View on GitHub (pinned to 6e04ca5ff0)