honojs/hono · critical · JwtTokenSignatureMismatched
token(${token}) signature mismatched
Error message
token(${token}) signature mismatched What it means
Thrown after cryptographic verification fails: the signature bytes in the token do not match the header+payload when verified with the provided public key and algorithm. The token is tampered with or signed with a different key.
Source
Thrown at src/utils/jwt/jwt.ts:184
? aud.test(payloadAud)
: typeof aud === 'string'
? payloadAud === aud
: Array.isArray(aud) && aud.includes(payloadAud)
)
if (!matched) {
throw new JwtTokenAudience(aud, payload.aud)
}
}
const headerPayload = token.substring(0, token.lastIndexOf('.'))
const verified = await verifying(
publicKey,
alg,
decodeBase64Url(tokenParts[2]),
utf8Encoder.encode(headerPayload)
)
if (!verified) {
throw new JwtTokenSignatureMismatched(token)
}
return payload
}
// Symmetric algorithms that are not allowed for JWK verification
const symmetricAlgorithms: SymmetricAlgorithm[] = [
AlgorithmTypes.HS256,
AlgorithmTypes.HS384,
AlgorithmTypes.HS512,
]
export const verifyWithJwks = async (
token: string,
options: {
keys?: HonoJsonWebKey[]
jwks_uri?: string
verification?: VerifyOptionsView on GitHub (pinned to e2740d5a1b)
Solutions
- Confirm the public key/JWK corresponds to the private key that signed the token (check kid against JWKS)
- Ensure the alg passed to verify matches the token header's alg
- Re-fetch JWKS if keys may have rotated
- Reject the request: a signature mismatch may indicate tampering — do not retry with looser settings
- Check the token is not being altered (e.g. URL-decoding issues, whitespace)
Example fix
// before
await verify(token, wrongKey, { alg: 'RS256' }) // header says RS384
// after
const header = decodeHeader(token)
await verify(token, correctKey, { alg: header.alg }) Defensive patterns
Strategy: try-catch
Validate before calling
const header = decodeHeader(token)
if (header.alg !== opts.alg) throw new Error('alg mismatch before verify') Try / catch
try { await verify(token, key, { alg }) } catch (e) { if (e instanceof JwtTokenSignatureMismatched) return unauthorized('invalid signature'); throw e } Prevention
- Refresh/cached JWKS on kid miss to handle rotation
- Pass header.alg to verify rather than hardcoding
When it happens
Trigger: verify() computes verifying(publicKey, alg, signature, headerPayload) which returns false — wrong public key, wrong alg parameter, or a forged/modified token.
Common situations: Using the wrong JWKS/public key after key rotation; alg option not matching the token header's alg; token truncated or modified in transit; using a staging key against prod tokens; base64url corruption from URL encoding issues.
Related errors
- Unauthorized
- symmetric algorithm "${alg}" is not allowed for JWK verifica
- algorithm "${alg}" is not in the allowed list: [${allowedAlg
- Path traversal detected: "${filePath}" is outside the output
- JWK auth middleware requires options for either "keys" or "j
AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28).
Data as JSON: /api/errors/44e77fc638cce2ac.
Report an issue: GitHub.