{"record":{"id":"44e77fc638cce2ac","repo":"honojs/hono","slug":"token-token-signature-mismatched","errorCode":null,"errorMessage":"token(${token}) signature mismatched","messagePattern":"token\\((.+?)\\) signature mismatched","errorType":"exception","errorClass":"JwtTokenSignatureMismatched","httpStatus":null,"severity":"critical","filePath":"src/utils/jwt/jwt.ts","lineNumber":184,"sourceCode":"        ? aud.test(payloadAud)\n        : typeof aud === 'string'\n          ? payloadAud === aud\n          : Array.isArray(aud) && aud.includes(payloadAud)\n    )\n    if (!matched) {\n      throw new JwtTokenAudience(aud, payload.aud)\n    }\n  }\n\n  const headerPayload = token.substring(0, token.lastIndexOf('.'))\n  const verified = await verifying(\n    publicKey,\n    alg,\n    decodeBase64Url(tokenParts[2]),\n    utf8Encoder.encode(headerPayload)\n  )\n  if (!verified) {\n    throw new JwtTokenSignatureMismatched(token)\n  }\n\n  return payload\n}\n\n// Symmetric algorithms that are not allowed for JWK verification\nconst symmetricAlgorithms: SymmetricAlgorithm[] = [\n  AlgorithmTypes.HS256,\n  AlgorithmTypes.HS384,\n  AlgorithmTypes.HS512,\n]\n\nexport const verifyWithJwks = async (\n  token: string,\n  options: {\n    keys?: HonoJsonWebKey[]\n    jwks_uri?: string\n    verification?: VerifyOptions","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/honojs/hono/blob/e2740d5a1bd0b4254e517e3af8b60789284bc7bd/src/utils/jwt/jwt.ts#L166-L202","documentation":"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.","triggerScenarios":"verify() computes verifying(publicKey, alg, signature, headerPayload) which returns false — wrong public key, wrong alg parameter, or a forged/modified token.","commonSituations":"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.","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)"],"exampleFix":"// before\nawait verify(token, wrongKey, { alg: 'RS256' }) // header says RS384\n// after\nconst header = decodeHeader(token)\nawait verify(token, correctKey, { alg: header.alg })","handlingStrategy":"try-catch","validationCode":"const header = decodeHeader(token)\nif (header.alg !== opts.alg) throw new Error('alg mismatch before verify')","typeGuard":null,"tryCatchPattern":"try { await verify(token, key, { alg }) } catch (e) { if (e instanceof JwtTokenSignatureMismatched) return unauthorized('invalid signature'); throw e }","preventionTips":["Refresh/cached JWKS on kid miss to handle rotation","Pass header.alg to verify rather than hardcoding"],"tags":["jwt","signature-verification","security","cryptography"],"backgroundTag":"jwt-signature-verification-failed","analyzedSha":"e2740d5a1bd0b4254e517e3af8b60789284bc7bd","analyzedAt":"2026-08-28T10:18:08.750Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}