Skip to content

feat(jwt): add optional requireAudience to verifyJwt#130

Open
EfeDurmaz16 wants to merge 1 commit into
agentcommercekit:mainfrom
EfeDurmaz16:jwt-require-audience
Open

feat(jwt): add optional requireAudience to verifyJwt#130
EfeDurmaz16 wants to merge 1 commit into
agentcommercekit:mainfrom
EfeDurmaz16:jwt-require-audience

Conversation

@EfeDurmaz16

@EfeDurmaz16 EfeDurmaz16 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What

Adds an optional requireAudience to verifyJwt. When true, a verified token
whose aud claim is absent or empty (empty string, [], [""]) is rejected.

Why

did-jwt's verifyJWT only runs its audience match when the token carries an
aud claim. So a token that omits aud verifies even when the caller supplies
an audience. verifyJwt already layers an issuer post-check on top of
did-jwt; this adds an opt-in audience-presence check in the same shape, so a
caller that supplies audience can also require the claim to exist.

This gap is live in this repo: packages/ack-id/src/a2a/verify.ts calls
verifyJwt(jwt, { audience: did, ... }) with a comment that the message is
"intended for the provided DID", yet an aud-less token verifies there today.
I have kept this PR to the jwt package alone; wiring requireAudience: true
into the ack-id A2A verifiers is a natural follow-up but is a behavior change
in another package, so I would rather agree the direction first.

Design note (happy to adjust)

The opt-in boolean is the conservative, non-breaking choice. An alternative is
to infer the requirement whenever an audience is supplied (jose-style), which
would be a behavior change. Glad to open this as an issue first and take
whichever shape you prefer.

Change

  • requireAudience?: boolean on VerifyJwtOptions
  • a small hasAudience helper (non-empty string or array with a non-empty
    entry) so empty audiences do not slip through
  • default off, so existing behaviour is unchanged (backward compatible)

Tests

verify.test.ts: the realistic path ({ audience, requireAudience: true },
asserting audience is forwarded and requireAudience is not), plus
missing-aud and empty-array rejection. pnpm --filter @agentcommercekit/jwt test -> 21 passing. Changeset included (minor).

AI assistance disclosure

Per the repository AI policy: implemented and tested by gpt 5.6-sol and fable 5, then reviewed and understood by me. I can explain the implementation and its trade-offs without AI aid. Tests, typecheck, and formatting pass locally against the package suite.

Summary by CodeRabbit

  • New Features

    • Added an optional requireAudience setting for JWT verification.
    • When enabled, tokens must include a non-empty audience claim.
    • Existing behavior remains unchanged by default.
  • Bug Fixes

    • JWT verification now clearly rejects tokens missing a required audience with an informative error.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@EfeDurmaz16, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 64dfe7af-7de0-45ab-b7e4-83134215370d

📥 Commits

Reviewing files that changed from the base of the PR and between b6875fa and ea70b1f.

📒 Files selected for processing (3)
  • .changeset/jwt-require-audience.md
  • packages/jwt/src/verify.test.ts
  • packages/jwt/src/verify.ts

Walkthrough

verifyJwt adds an optional requireAudience option that rejects tokens without a non-empty aud claim when enabled. Tests cover forwarding behavior and missing or empty audience claims, and a changeset documents the minor release update.

Changes

JWT audience requirement

Layer / File(s) Summary
Audience option and enforcement
packages/jwt/src/verify.ts
Adds requireAudience to VerifyJwtOptions, preserves audience forwarding to did-jwt, and rejects missing or empty audience claims when enabled.
Audience behavior tests and release metadata
packages/jwt/src/verify.test.ts, .changeset/jwt-require-audience.md
Tests audience forwarding and rejection cases; documents the optional minor update.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: venables

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an optional requireAudience flag to verifyJwt.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/jwt/src/verify.test.ts (1)

160-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for an empty-string audience.

The contract includes aud: "", but these tests cover only aud: [] and a missing claim. Add a case that verifies requireAudience: true rejects the empty string branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/jwt/src/verify.test.ts` around lines 160 - 193, Add a test alongside
the existing empty-array case in the verifyJwt tests, using a mock verified
payload with aud set to an empty string and requireAudience enabled. Assert that
verifyJwt rejects with the existing “JWT audience is required but missing”
error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/jwt/src/verify.test.ts`:
- Around line 149-156: Update the verifyJWT invocation assertions in this test
to inspect this test’s call rather than a prior suite call: clear the mock
history in beforeEach or reference the latest mock call before asserting
requireAudience is absent. Preserve the existing audience assertion.

---

Nitpick comments:
In `@packages/jwt/src/verify.test.ts`:
- Around line 160-193: Add a test alongside the existing empty-array case in the
verifyJwt tests, using a mock verified payload with aud set to an empty string
and requireAudience enabled. Assert that verifyJwt rejects with the existing
“JWT audience is required but missing” error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d341f587-2a22-4760-bf48-e95f555af5fe

📥 Commits

Reviewing files that changed from the base of the PR and between 43a066c and b6875fa.

📒 Files selected for processing (3)
  • .changeset/jwt-require-audience.md
  • packages/jwt/src/verify.test.ts
  • packages/jwt/src/verify.ts

Comment thread packages/jwt/src/verify.test.ts
@EfeDurmaz16
EfeDurmaz16 force-pushed the jwt-require-audience branch from b6875fa to ea70b1f Compare July 22, 2026 00:32
@EfeDurmaz16

Copy link
Copy Markdown
Contributor Author

@venables a review when convenient would be great. Companion to #129: an opt-in requireAudience on verifyJwt (the motivating gap is live at ack-id/a2a/verify.ts, noted in the description). Happy to take this issue-first or wire the ack-id call sites if you prefer; CodeRabbit's note is addressed. CI needs a maintainer 'approve and run'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant