Skip to content

Commit

Permalink
fix: allow ID Token auth_time to be present even if client.require_au…
Browse files Browse the repository at this point in the history
…th_time is false
  • Loading branch information
panva committed Jun 20, 2024
1 parent c0b1cc3 commit caa9ab3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 29 deletions.
14 changes: 10 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2715,8 +2715,11 @@ async function processGenericAccessTokenResponse(
throw new OPE('unexpected ID Token "azp" (authorized party) claim value')
}

if (client.require_auth_time && typeof claims.auth_time !== 'number') {
throw new OPE('unexpected ID Token "auth_time" (authentication time) claim value')
if (
claims.auth_time !== undefined &&
(!Number.isFinite(claims.auth_time) || Math.sign(<number>claims.auth_time) !== 1)
) {
throw new OPE('ID Token "auth_time" (authentication time) must be a positive number')
}

idTokenClaims.set(json, <IDToken>claims)
Expand Down Expand Up @@ -3937,8 +3940,11 @@ export async function validateDetachedSignatureResponse(
throw new OPE('invalid ID Token "s_hash" (state hash) claim value')
}

if (client.require_auth_time !== undefined && typeof claims.auth_time !== 'number') {
throw new OPE('unexpected ID Token "auth_time" (authentication time) claim value')
if (
claims.auth_time !== undefined &&
(!Number.isFinite(claims.auth_time) || Math.sign(<number>claims.auth_time) !== 1)
) {
throw new OPE('ID Token "auth_time" (authentication time) must be a positive number')
}

maxAge ??= client.default_max_age ?? skipAuthTimeCheck
Expand Down
47 changes: 22 additions & 25 deletions test/authorization_code.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -828,32 +828,29 @@ test('processAuthorizationCodeOpenIDResponse() nonce checks', async (t) => {
test('processAuthorizationCodeOpenIDResponse() auth_time checks', async (t) => {
const tIssuer: lib.AuthorizationServer = { ...issuer, jwks_uri: endpoint('jwks') }

await t.throwsAsync(
lib.processAuthorizationCodeOpenIDResponse(
tIssuer,
{
...client,
require_auth_time: true,
},
getResponse(
JSON.stringify({
access_token: 'token',
token_type: 'Bearer',
id_token: await new jose.SignJWT({
auth_time: '0',
})
.setProtectedHeader({ alg: 'RS256' })
.setIssuer(issuer.issuer)
.setSubject('urn:example:subject')
.setAudience(client.client_id)
.setExpirationTime('5m')
.setIssuedAt()
.sign(t.context.RS256.privateKey),
}),
for (const auth_time of [0, -1, null, '1', [], {}, true]) {
await t.throwsAsync(
lib.processAuthorizationCodeOpenIDResponse(
tIssuer,
client,
getResponse(
JSON.stringify({
access_token: 'token',
token_type: 'Bearer',
id_token: await new jose.SignJWT({ auth_time })
.setProtectedHeader({ alg: 'RS256' })
.setIssuer(issuer.issuer)
.setSubject('urn:example:subject')
.setAudience(client.client_id)
.setExpirationTime('5m')
.setIssuedAt()
.sign(t.context.RS256.privateKey),
}),
),
),
),
{ message: 'unexpected ID Token "auth_time" (authentication time) claim value' },
)
{ message: 'ID Token "auth_time" (authentication time) must be a positive number' },
)
}
})

test('processAuthorizationCodeOpenIDResponse() azp checks', async (t) => {
Expand Down

0 comments on commit caa9ab3

Please sign in to comment.