fix(backend): Fix JWT array audience validation#8470
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
📝 WalkthroughWalkthroughThe pull request modifies JWT audience claim validation to handle array-type Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
This could be for a follow-up but I think we could change the types in
from unknown tostring | string[]
Also I understand skipping verification if we have no expected audience, but it seems odd to skip it if we do expect something and the token doesn't provide any.
Summary
This fixes JWT audience validation for tokens whose
audclaim is an array.verifyJwtnow passes the rawaudclaim and configuredaudienceoption intoassertAudienceClaim. The assertion helper already normalizes string and string-array inputs, so this lets it evaluate array audiences correctly.Scope
This does not mean default Clerk session tokens have an
audclaim. They generally do not, and this PR does not change the existing behavior for tokens with noaud: if the token has no audience claim,verifyJwtstill skips audience validation.The bug only applies when both of these are true:
audienceaudas a string arrayThat shape is valid JWT syntax and is already represented in this package's M2M token parsing fallback (
aud?: string[]). Clerk-issued M2M tokens also allow custom claims, andaudis not reserved there. So the fix is scoped to correctly enforcing the existingaudienceoption when an arrayaudis present, not to introducing audience binding for all Clerk tokens.Root Cause
verifyJwtwrapped both values before calling the assertion:When the token already had
audas a string array, the assertion received a nested array. That shape skipped both validation branches: it was not a string, and it was not an array of strings. The function returned without enforcing the configured audience.Tests
audwhen it includes the configured audienceaudwhen it does not include the configured audienceValidation
NODE_OPTIONS=--no-experimental-webstorage pnpm --filter @clerk/backend buildpnpm --filter @clerk/backend build:runtimeNODE_OPTIONS=--no-experimental-webstorage pnpm exec vitest run src/jwt/__tests__/assertions.test.ts src/jwt/__tests__/verifyJwt.test.ts --environment node --typecheck.enabled=falsepnpm --filter @clerk/backend format:checkgit diff --check