Skip to content

security: coordinated JWT issuer/audience hardening across AuthGuard, betterauth.ts, and mcp.handler.ts #624

Description

@coderabbitai

Context

Currently, jwtVerify(token, JWKS) in both protocol/src/guards/auth.guard.ts (Line 30) and protocol/src/controllers/mcp.handler.ts (Lines 88–100) validates signature and expiration only — it does not validate the iss (issuer) or aud (audience) claims.

Better Auth's JWT plugin (protocol/src/lib/betterauth/betterauth.ts) currently embeds issuer: BASE_URL when issuing tokens but does not embed an aud claim. This means:

  • Any cryptographically valid JWT from the same JWKS with a string id or sub claim can authenticate to any endpoint, regardless of intended scope.
  • Adding audience validation unilaterally would immediately reject all existing tokens (since no aud is embedded today).

Required coordinated change

This fix must be done atomically across three files to avoid breaking existing tokens:

  1. protocol/src/lib/betterauth/betterauth.ts — Add an audience claim (e.g., BASE_URL or a service-specific string) to the JWT plugin's definePayload or JWT config.
  2. protocol/src/guards/auth.guard.ts — Update jwtVerify(token, JWKS) to jwtVerify(token, JWKS, { issuer: BASE_URL, audience: '<agreed_value>' }).
  3. protocol/src/controllers/mcp.handler.ts — Same update to the jwtVerify call in authResolver.resolveUserId.

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions