authExtensions docs say custom claims override reserved JWT claims, but implementation keeps reserved claims authoritative
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 74/100
- Issue type
- Documentation
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- authentication, documentation
Research direction
Start in packages/client/src/client/authExtensions.ts and read the PrivateKeyJwtProviderOptions.claims documentation alongside createPrivateKeyJwtAuth(). Locate the related auth extension tests, then update the wording to explain that additional claims are included while reserved standard claims remain SDK-controlled. Done means the documentation matches runtime behavior and a regression test demonstrates the reserved-claim behavior.
Written by the indexing model from the issue text.
Description
Summary
PrivateKeyJwtProviderOptions.claims currently documents overlapping custom claims as taking precedence over the SDK's standard JWT claims, but the implementation keeps the reserved claims authoritative.
This looks like a docs / contract mismatch rather than a runtime bug or security issue.
Current docs
packages/client/src/client/authExtensions.ts says:
These are merged with the standard claims (
iss,sub,aud,exp,iat,jti), with custom claims taking precedence for any overlapping keys.
Actual behavior
createPrivateKeyJwtAuth() constructs claims from { ...baseClaims, ...options.claims }, but then immediately calls:
.setIssuer(options.issuer).setSubject(options.subject).setAudience(audience).setIssuedAt(now).setExpirationTime(now + lifetimeSeconds).setJti(jti)
Those setters overwrite overlapping values from options.claims, so the SDK's reserved claims remain authoritative.
Minimal reproduction
const addClientAuth = createPrivateKeyJwtAuth({
issuer: 'client-id',
subject: 'client-id',
privateKey: 'a-string-secret-at-least-256-bits-long',
alg: 'HS256',
audience: 'https://aud.example.com',
claims: {
iss: 'override-issuer',
sub: 'override-subject',
aud: 'https://override.example.com',
tenant_id: 'org-123'
}
});
Decoding the resulting JWT shows:
iss === 'client-id'sub === 'client-id'aud === 'https://aud.example.com'tenant_id === 'org-123'
So additional custom claims are included, but overlapping reserved claims are not overridden.
Why this matters
This can mislead users into thinking they can customize reserved JWT claims through claims, when in practice only non-overlapping claims are honored.
Suggested resolution
I think the smallest fix is to align the docs/tests with the current runtime behavior:
- clarify that additional custom claims are included
- clarify that reserved standard claims are still set explicitly by the SDK and are not overridden
- add a regression test showing the current behavior
If maintainers prefer the opposite behavior, that would likely deserve a separate design discussion because it changes runtime semantics.
- Dominant language
- TypeScript
- Stars
- 13.4k
- Forks
- 2.2k
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from modelcontextprotocol/typescript-sdk
-
Auth metadata discovery: fallback URL built on resource host instead of authorization-server host Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
modelcontextprotocol/typescript-sdk#2783 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
modelcontextprotocol/typescript-sdk#2766 · 1 comment ·
-
Difficulty 2/5 1-2 days Newbie friendliness 72/100
All issues in modelcontextprotocol/typescript-sdk
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100