{"record":{"id":"7295075b3350687d","repo":"honojs/hono","slug":"expected-audience-array-isarray-expected-exp","errorCode":null,"errorMessage":"expected audience \"${Array.isArray(expected) ? expected.join(', ') : expected}\", got \"${aud}\"","messagePattern":"expected audience \"(.+?)\", got \"(.+?)\"","errorType":"exception","errorClass":"JwtTokenAudience","httpStatus":null,"severity":"error","filePath":"src/utils/jwt/jwt.ts","lineNumber":172,"sourceCode":"      throw new JwtTokenIssuer(iss, payload.iss)\n    }\n  }\n\n  if (aud) {\n    if (!payload.aud) {\n      throw new JwtPayloadRequiresAud(payload)\n    }\n\n    const audiences = Array.isArray(payload.aud) ? payload.aud : [payload.aud]\n    const matched = audiences.some((payloadAud): boolean =>\n      aud instanceof RegExp\n        ? 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","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/honojs/hono/blob/e2740d5a1bd0b4254e517e3af8b60789284bc7bd/src/utils/jwt/jwt.ts#L154-L190","documentation":"Thrown when the token's aud claim does not match the expected audience. Expected can be a string, RegExp, or array; every payload audience value is tested and at least one must match.","triggerScenarios":"verify(token, key, { aud }) where aud is a string that differs from every entry in payload.aud, a RegExp that matches none, or an array that contains none of the payload's audience values.","commonSituations":"Client verified an ID token (aud = client_id) while expecting the API's audience; audience identifier typo; multiple APIs sharing tokens with different aud identifiers; microservice verified a token intended for another service.","solutions":["Decode the token and read the actual aud value","Align the configured audience with what the IdP emits (exact string)","For multiple valid audiences pass an array: aud: ['api-a', 'api-b']","Use a RegExp if audiences share a pattern","Ensure you validate access tokens (not ID tokens) with your API's audience"],"exampleFix":"// before\nawait verify(token, key, { aud: 'my-api' })\n// after\nawait verify(token, key, { aud: ['my-api', 'my-api-v2'] })","handlingStrategy":"try-catch","validationCode":"const audiences = Array.isArray(payload.aud) ? payload.aud : [payload.aud]\nif (!audiences.includes(expectedAud)) console.warn('aud mismatch:', audiences)","typeGuard":null,"tryCatchPattern":"try { await verify(token, key, { aud }) } catch (e) { if (e instanceof JwtTokenAudience) return unauthorized(); throw e }","preventionTips":["Pass an array when multiple audiences are valid","Match the audience identifier exactly as registered in the IdP"],"tags":["jwt","audience-validation","authentication"],"backgroundTag":"jwt-audience-mismatch","analyzedSha":"e2740d5a1bd0b4254e517e3af8b60789284bc7bd","analyzedAt":"2026-08-28T10:18:08.750Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}