OpenNHP/opennhp · error
unexpected signing method
Error message
unexpected signing method: %v
What it means
During jwt.Parse, the keyfunc verifies the token's alg header is an ECDSA signing method; anything else (RS256, HS256, none) returns 'unexpected signing method: %v'. This prevents algorithm-confusion attacks where a token signed with a weaker or different algorithm is presented while the server holds an ECDSA key.
Solutions
- Fix the client to sign with ES256 (ECDSA P-256), matching the embedded P-256 JWK.
- Check the token's alg header offline to see what was actually used.
- Reject or route non-ECDSA tokens to the appropriate verification path instead of VerifyJWT.
- Ensure no client library fallback silently switches algorithms (explicitly set SigningMethodES256).
- If RS256 is expected from some clients, embed/use the matching RSA key rather than ECDSA in the keyfunc.
Example fix
// client side before: defaulting to another method token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // after token := jwt.NewWithClaims(jwt.SigningMethodES256, claims) s, err := token.SignedString(ecdsaPrivateKey)
Defensive patterns
Strategy: validation
Validate before calling
func algIsECDSA(token string) bool {
parts := strings.Split(token, ".")
if len(parts) != 3 { return false }
hdr, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil { return false }
var h struct{ Alg string `json:"alg"` }
if json.Unmarshal(hdr, &h) != nil { return false }
return strings.HasPrefix(h.Alg, "ES")
} Try / catch
token, err := VerifyJWT(rawToken)
if err != nil && strings.Contains(err.Error(), "unexpected signing method") {
// wrong algorithm / possible alg-confusion: return 401, do not retry
} Prevention
- Explicitly pin SigningMethodES256 on the client signer.
- Never accept tokens from issuers using other algorithms in this endpoint.
- Keep the keyfunc allowlist strict (ECDSA only).
- Test with a deliberately wrong-alg token to confirm rejection.
- Update client keys, not algorithms, when rotating credentials.
When it happens
Trigger: VerifyJWT receives a token whose header alg is not ES256-family ECDSA — e.g. RS256 tokens from an OIDC provider, HS256 tokens, or alg:none tokens — and jwt.Parse invokes the keyfunc.
Common situations: Client misconfigured to sign with RSA or HMAC instead of ES256; token issued by a generic auth service rather than the KBS attestation flow; crafted alg-confusion token from a probing client; library defaults changed between versions.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- failed to parse token
- missing or invalid jwk in header
- JWT signing key is not initialized
- invalid resource ID: potential path traversal attack
- invalid file name
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/3d27113884c65379.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/server/kbs/resource/resource.go:254
if err != nil {
return nil, fmt.Errorf("invalid x coordinate: %w", err)
}
yBytes, err := base64.RawURLEncoding.DecodeString(yStr)
if err != nil {
return nil, fmt.Errorf("invalid y coordinate: %w", err)
}
publicKey := &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: new(big.Int).SetBytes(xBytes),
Y: new(big.Int).SetBytes(yBytes),
}
// Now verify the token with the extracted public key
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) {
// Check signing method
if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return publicKey, nil
})
if err != nil {
return nil, err
}
return token, nil
}
View on GitHub (pinned to 6e04ca5ff0)