honojs/hono · error · JwtAlgorithmNotAllowed
algorithm "${alg}" is not in the allowed list: [${allowedAlg
Error message
algorithm "${alg}" is not in the allowed list: [${allowedAlgorithms.join(', ')}] What it means
Thrown by verifyWithJwks when the token header's alg is not in the options.allowedAlgorithms list. This whitelist prevents unexpected or downgrade algorithms from being accepted, independent of key availability.
Source
Thrown at src/utils/jwt/jwt.ts:225
const verifyOpts = options.verification || {}
const header = decodeHeader(token)
if (!isTokenHeader(header)) {
throw new JwtHeaderInvalid(header)
}
if (!header.kid) {
throw new JwtHeaderRequiresKid(header)
}
// Reject symmetric algorithms (HS256, HS384, HS512) to prevent algorithm confusion attacks
if (symmetricAlgorithms.includes(header.alg as SymmetricAlgorithm)) {
throw new JwtSymmetricAlgorithmNotAllowed(header.alg)
}
// Validate against allowed algorithms
if (!options.allowedAlgorithms.includes(header.alg as AsymmetricAlgorithm)) {
throw new JwtAlgorithmNotAllowed(header.alg, options.allowedAlgorithms)
}
let verifyKeys = options.keys ? [...options.keys] : undefined
if (options.jwks_uri) {
const response = await fetch(options.jwks_uri, init)
if (!response.ok) {
throw new Error(`failed to fetch JWKS from ${options.jwks_uri}`)
}
const data = (await response.json()) as { keys?: JsonWebKey[] }
if (!data.keys) {
throw new Error('invalid JWKS response. "keys" field is missing')
}
if (!Array.isArray(data.keys)) {
throw new Error('invalid JWKS response. "keys" field is not an array')
}
verifyKeys ??= []
verifyKeys.push(...(data.keys as HonoJsonWebKey[]))View on GitHub (pinned to e2740d5a1b)
Solutions
- Decode the token header to see the actual alg value
- Add that alg to allowedAlgorithms (e.g. ['RS256','ES256'])
- If the alg is unexpected (e.g. none/HS*), treat it as suspicious and reject
- Sync the whitelist with the algorithms your IdP advertises in its JWKS metadata
Example fix
// before
await verifyWithJwks(es256Token, { allowedAlgorithms: ['RS256'], ... })
// after
await verifyWithJwks(es256Token, { allowedAlgorithms: ['RS256', 'ES256'], ... }) Defensive patterns
Strategy: validation
Validate before calling
const header = decodeHeader(token)
if (!allowedAlgorithms.includes(header.alg)) throw new Error(`alg ${header.alg} not allowed`) Try / catch
try { await verifyWithJwks(token, opts) } catch (e) { if (e instanceof JwtAlgorithmNotAllowed) return unauthorized('alg not allowed'); throw e } Prevention
- Keep allowedAlgorithms in sync with the IdP's advertised algorithms
- Include all legitimate algorithms your multi-tenant providers use
When it happens
Trigger: verifyWithJwks(token, { allowedAlgorithms: ['RS256'], ... }) on a token signed with e.g. ES256 or PS256, so the includes() check fails.
Common situations: IdP switched signing algorithm (e.g. RS256 → ES256) after rotation or config change; default allowedAlgorithms not matching the provider; multi-tenant app verifying tokens from providers with different algorithms.
Related errors
- token(${token}) signature mismatched
- symmetric algorithm "${alg}" is not allowed for JWK verifica
- Path traversal detected: "${filePath}" is outside the output
- JWK auth middleware requires options for either "keys" or "j
- invalid credentials structure
AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28).
Data as JSON: /api/errors/e8b199ff580cb426.
Report an issue: GitHub.