Skip to content

Commit

Permalink
feat: allow fragment response as URL in validateDetachedSignatureResp…
Browse files Browse the repository at this point in the history
…onse
  • Loading branch information
panva committed Jan 18, 2024
1 parent f1126f1 commit bcbe2f5
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 9 deletions.
12 changes: 7 additions & 5 deletions conformance/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ export const green = (options?: MacroOptions) =>
throw new Error()
}

let currentUrl: URL | URLSearchParams = new URL(authorization_endpoint_response_redirect)
let currentUrl = new URL(authorization_endpoint_response_redirect)

let sub: string
let access_token: string
Expand All @@ -379,15 +379,17 @@ export const green = (options?: MacroOptions) =>
if (usesJarm(variant)) {
params = await oauth.validateJwtAuthResponse(as, client, currentUrl, state)
} else if (response_type === 'code id_token') {
currentUrl = new URLSearchParams(currentUrl.hash.slice(1))
const idToken = currentUrl.get('id_token')!
const fragmentParams = new URLSearchParams(currentUrl.hash.slice(1))
const idToken = fragmentParams.get('id_token')!
let decrypted
if (decodeProtectedHeader(idToken).enc) {
currentUrl.set('id_token', await decryptIdToken(idToken))
fragmentParams.set('id_token', await decryptIdToken(idToken))
decrypted = true
}
params = await oauth.experimental_validateDetachedSignatureResponse(
as,
client,
currentUrl,
decrypted ? fragmentParams : currentUrl,
<string>nonce,
state,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ responses.
| :------ | :------ | :------ |
| `as` | [`AuthorizationServer`](../interfaces/AuthorizationServer.md) | Authorization Server Metadata. |
| `client` | [`Client`](../interfaces/Client.md) | Client Metadata. |
| `parameters` | [`URLSearchParams`]( https://developer.mozilla.org/docs/Web/API/URLSearchParams ) | Authorization Response. |
| `parameters` | [`URLSearchParams`]( https://developer.mozilla.org/docs/Web/API/URLSearchParams ) \| [`URL`]( https://developer.mozilla.org/docs/Web/API/URL ) | Authorization Response parameters as URLSearchParams or an instance of URL with parameters in a fragment/hash. |
| `expectedNonce` | `string` | Expected ID Token `nonce` claim value. |
| `expectedState?` | `string` \| typeof [`expectNoState`](../variables/expectNoState.md) | Expected `state` parameter value. Default is [expectNoState](../variables/expectNoState.md). |
| `maxAge?` | `number` \| typeof [`skipAuthTimeCheck`](../variables/skipAuthTimeCheck.md) | ID Token [`auth_time`](../interfaces/IDToken.md#auth_time) claim value will be checked to be present and conform to the `maxAge` value. Use of this option is required if you sent a `max_age` parameter in an authorization request. Default is [`client.default_max_age`](../interfaces/Client.md#default_max_age) and falls back to [skipAuthTimeCheck](../variables/skipAuthTimeCheck.md). |
Expand Down
2 changes: 1 addition & 1 deletion examples/fapi1-advanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ let request: string
// one eternity later, the user lands back on the redirect_uri
{
// @ts-expect-error
const authorizationResponse: URLSearchParams = getAuthorizationResponse()
const authorizationResponse: URLSearchParams | URL = getAuthorizationResponseOrURLWithFragment()
const params = await oauth.experimental_validateDetachedSignatureResponse(
as,
client,
Expand Down
14 changes: 12 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3542,7 +3542,8 @@ async function idTokenHashMatches(data: string, actual: string, alg: JWSAlgorith
*
* @param as Authorization Server Metadata.
* @param client Client Metadata.
* @param parameters Authorization Response.
* @param parameters Authorization Response parameters as URLSearchParams or an instance of URL with
* parameters in a fragment/hash.
* @param expectedNonce Expected ID Token `nonce` claim value.
* @param expectedState Expected `state` parameter value. Default is {@link expectNoState}.
* @param maxAge ID Token {@link IDToken.auth_time `auth_time`} claim value will be checked to be
Expand All @@ -3561,7 +3562,7 @@ async function idTokenHashMatches(data: string, actual: string, alg: JWSAlgorith
export async function experimental_validateDetachedSignatureResponse(
as: AuthorizationServer,
client: Client,
parameters: URLSearchParams,
parameters: URLSearchParams | URL,
expectedNonce: string,
expectedState?: string | typeof expectNoState,
maxAge?: number | typeof skipAuthTimeCheck,
Expand All @@ -3570,6 +3571,15 @@ export async function experimental_validateDetachedSignatureResponse(
assertAs(as)
assertClient(client)

if (parameters instanceof URL) {
if (!parameters.hash.length) {
throw new TypeError(
'"parameters" as an instance of URL must contain a hash (fragment) with the Authorization Response parameters',
)
}
parameters = new URLSearchParams(parameters.hash.slice(1))
}

if (!(parameters instanceof URLSearchParams)) {
throw new TypeError('"parameters" must be an instance of URLSearchParams')
}
Expand Down

0 comments on commit bcbe2f5

Please sign in to comment.