diff --git a/src/lib/jwt_claims_set.ts b/src/lib/jwt_claims_set.ts index 205d37b6d4..ebc7a821e5 100644 --- a/src/lib/jwt_claims_set.ts +++ b/src/lib/jwt_claims_set.ts @@ -53,12 +53,14 @@ export default ( const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options - if (maxTokenAge !== undefined) requiredClaims.push('iat') - if (audience !== undefined) requiredClaims.push('aud') - if (subject !== undefined) requiredClaims.push('sub') - if (issuer !== undefined) requiredClaims.push('iss') + const presenceCheck = [...requiredClaims] - for (const claim of new Set(requiredClaims.reverse())) { + if (maxTokenAge !== undefined) presenceCheck.push('iat') + if (audience !== undefined) presenceCheck.push('aud') + if (subject !== undefined) presenceCheck.push('sub') + if (issuer !== undefined) presenceCheck.push('iss') + + for (const claim of new Set(presenceCheck.reverse())) { if (!(claim in payload)) { throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, claim, 'missing') } diff --git a/test/jwt/verify.test.mjs b/test/jwt/verify.test.mjs index e65ca3290e..82e11df519 100644 --- a/test/jwt/verify.test.mjs +++ b/test/jwt/verify.test.mjs @@ -418,6 +418,8 @@ test('requiredClaims claims check', async (t) => { .setProtectedHeader({ alg: 'HS256' }) .sign(t.context.secret) + const requiredClaims = ['nbf'] + for (const [claim, option] of [ ['iss', 'issuer'], ['aud', 'audience'], @@ -428,16 +430,15 @@ test('requiredClaims claims check', async (t) => { code: 'ERR_JWT_CLAIM_VALIDATION_FAILED', message: `missing required "${claim}" claim`, }) - await t.throwsAsync( - jwtVerify(jwt, t.context.secret, { [option]: 'foo', requiredClaims: ['nbf'] }), - { - code: 'ERR_JWT_CLAIM_VALIDATION_FAILED', - message: `missing required "${claim}" claim`, - }, - ) + await t.throwsAsync(jwtVerify(jwt, t.context.secret, { [option]: 'foo', requiredClaims }), { + code: 'ERR_JWT_CLAIM_VALIDATION_FAILED', + message: `missing required "${claim}" claim`, + }) } - await t.throwsAsync(jwtVerify(jwt, t.context.secret, { requiredClaims: ['nbf'] }), { + await t.throwsAsync(jwtVerify(jwt, t.context.secret, { requiredClaims }), { code: 'ERR_JWT_CLAIM_VALIDATION_FAILED', message: `missing required "nbf" claim`, }) + + t.deepEqual(requiredClaims, ['nbf']) })