feat(auth0-auth-js): add actor token support and act claim to Custom Token Exchange#175
feat(auth0-auth-js): add actor token support and act claim to Custom Token Exchange#175cschetan77 wants to merge 5 commits into
Conversation
- Added ActClaim interface (sub: string + open index signature for extra claims per RFC 8693)
- Added actorToken? and actorTokenType? to ExchangeProfileOptions
- Added act?: ActClaim property to TokenResponse
- Populated act from parsed ID token claims in fromTokenEndpointResponse()
auth-client.ts
- Removed actor_token and actor_token_type from PARAM_DENYLIST (they now have explicit typed params)
- Updated the denylist comment block to remove the stale bullet
- Added validateTokenTypeUri() — syntactic-only new URL() check, throws TokenExchangeError with a clear message
- In #exchangeProfileToken(): calls validateTokenTypeUri for both subjectTokenType and actorTokenType, then appends actor_token/actor_token_type to the request when present
auth-client.spec.ts
- New describe('exchangeToken — actor token support') block with 5 tests covering: params wired + act claim populated, act claim with extra fields, params absent when not provided, invalid URI validation (both params in one test), valid URI acceptance
77b32f4 to
1ef94d5
Compare
|
|
||
| tokenResponse.tokenType = response.token_type; | ||
| tokenResponse.issuedTokenType = (response as typeof response & { issued_token_type?: string }).issued_token_type; | ||
| const atClaims = decodeJwt(response.access_token); |
There was a problem hiding this comment.
What will happen if Auth0 issues an opaque token.
| tokenResponse.tokenType = response.token_type; | ||
| tokenResponse.issuedTokenType = (response as typeof response & { issued_token_type?: string }).issued_token_type; | ||
| const atClaims = decodeJwt(response.access_token); | ||
| tokenResponse.act = (claims?.act ?? atClaims.act) as ActClaim | undefined; |
There was a problem hiding this comment.
Does that mean, tokenResponse would always have act ?
Because fromTokenEndpointResponse is called from multiple places.
|
| * behalf of the subject. | ||
| * | ||
| * @see {@link https://www.rfc-editor.org/rfc/rfc8693#section-4.1 RFC 8693 Section 4.1} | ||
| */ |
There was a problem hiding this comment.
The act claim is defined in Section 4.4 ("Delegation Semantics"), not 4.1. Section 4.1 is the token exchange response structure.
Should be #section-4.4. (Same fix landed on the Android and Swift CTE PRs.)
| * the acting party on whose behalf the subject token was exchanged. | ||
| * | ||
| * @see {@link https://www.rfc-editor.org/rfc/rfc8693#section-4.1 RFC 8693 Section 4.1} | ||
| */ |
There was a problem hiding this comment.
Same as the ActClaim interface above: act is defined in Section 4.4, not 4.1. Should be #section-4.4.
|
|
||
| validateSubjectToken(options.subjectToken); | ||
| validateTokenTypeUri(options.subjectTokenType, 'subjectTokenType'); | ||
|
|
There was a problem hiding this comment.
Two concerns here:
-
The team aligned that token-type URI validation stays server-side, no other SDK (Swift, Android, spa-js) does client-side URI validation. Adding it here for
subjectTokenType(which previously had none) breaks that alignment and is a behavior change for existing callers. -
new URL()is the wrong validator and risks false rejections. It can reject values the Auth0 server would actually accept, turning a server-side concern into a client-side breaking change on upgrade. (new URL('urn:acme:custom-token')happens to pass, but the general class of valid token-type identifiers isn't guaranteed to parse as a WHATWG URL.)
| 'subject_token_type', | ||
| 'requested_token_type', | ||
| 'actor_token', | ||
| 'actor_token_type', |
There was a problem hiding this comment.
A caller can again pass actor_token through extra, which is no longer guarded. The typed param is the documented path.
Description
Extends the Custom Token Exchange (CTE) implementation in
auth0-auth-jsto supportRFC 8693delegation flows via actor tokens.actorTokenandactorTokenTypeoptional fields toExchangeProfileOptions, which are forwarded asactor_tokenandactor_token_typein the token request.ActClaiminterface({ sub: string; [key: string]: unknown })per RFC 8693 Section 4.1, the index signature allows for additional server-provided fields (e.g. chained delegation, iss).subjectTokenTypeandactorTokenTypevia new URL(), throws TokenExchangeError before the network request if invalid, semantic namespace validation remains on the Auth0 serveractor_tokenandactor_token_typefrom PARAM_DENYLIST since they are now first-class typed parametersTesting
Unit Tests
Checklist