Skip to content

fix: bind aud claim on signed user tokens#94

Merged
Bccorb merged 1 commit into
mainfrom
fix/set-token-audience
Jul 20, 2026
Merged

fix: bind aud claim on signed user tokens#94
Bccorb merged 1 commit into
mainfrom
fix/set-token-audience

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Problem

The Seamless adapter now verifies signed auth responses with aud === audience (the unreleased verify-audience-binding change in seamless-auth-server), but no signer here ever set an aud claim. jose rejects a token that lacks a claim it was told to check, so once that adapter change ships, every handler calling verifySignedAuthResponse fails: login, finishLogin, finishRegister, OAuth, OTP, magic-link, and organization-switch. This is a release blocker on both sides.

Core's tests mock jose, which is why CI did not catch it.

Fix

signAccessToken, signRefreshToken, and signEphemeralToken now call .setAudience(ISSUER) in addition to .setIssuer(ISSUER). The deployment contract requires the adopter's audience to equal its authServerUrl, which is byte-identical to this server's ISSUER, so aud === ISSUER is exactly what the adapter checks. The claim is additive and ignored by verifiers that do not check it (the API's own sessionService verifies issuer only).

The token unit test now captures and asserts the bound audience, closing the jose-mock blind spot.

Verification

  • Full suite: 951 passing, 1 skipped. Typecheck and format clean.
  • End to end with real jose against the built core and a live JWKS endpoint: a token with aud bound is accepted (sub returned); a token without it is rejected. This reproduces the blocker and confirms the fix.

Coordination

Must release together with the verify-audience-binding change in seamless-auth-server. See the fixed M2M service-token contract (iss=seamless-portal-api, aud=seamless-auth), which is separate from these user-token claims and unchanged here.

Signers set aud equal to ISSUER so the Seamless adapter, which now verifies
signed auth responses with aud === audience, accepts them. The deployment
contract requires the adopter's audience to equal its authServerUrl, which is
byte-identical to this server's ISSUER. Without the claim, jose rejects every
token the adapter checks, breaking login, registration, OAuth, OTP, magic-link,
and organization-switch once the adapter audience binding ships.
@Bccorb
Bccorb merged commit ff8067d into main Jul 20, 2026
2 of 3 checks passed
@Bccorb
Bccorb deleted the fix/set-token-audience branch July 24, 2026 02:35
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