deno.land / x / oauth4webapi@v1.2.2 / test / jwks_lifecycle.test.ts

jwks_lifecycle.test.ts
View Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import anyTest, { type TestFn } from 'ava'import setup, { type Context, teardown, issuer, getResponse, endpoint, client } from './_setup.js'import * as lib from '../src/index.js'import * as jose from 'jose'import timekeeper from 'timekeeper'
const test = anyTest as TestFn<Context>
test.before(setup)test.after(teardown)
test.serial('jwks_uri force refetch', async (t) => { const now = Date.now() timekeeper.freeze(now)
let key = await lib.generateKeyPair('ES256')
t.context .intercept({ path: '/jwks-force-refetch', method: 'GET', }) .reply(200, { keys: [await jose.exportJWK(key.publicKey)], })
const as: lib.AuthorizationServer = { ...issuer, jwks_uri: endpoint('jwks-force-refetch'), userinfo_signing_alg_values_supported: ['ES256'], } const c: lib.Client = { ...client, }
let jwt = await new jose.SignJWT({ sub: 'subject' }) .setProtectedHeader({ alg: 'ES256' }) .sign(key.privateKey)
let response = getResponse(jwt, { headers: new Headers({ 'content-type': 'application/jwt' }) })
await lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response) await lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response)
timekeeper.travel(now + 299 * 1000) await lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response) timekeeper.travel(now + 300 * 1000)
// re-fetch forced await t.throwsAsync(() => lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response))})
test.serial('jwks_uri refetch if off cooldown and needed', async (t) => { const now = Date.now() timekeeper.freeze(now)
let key = await lib.generateKeyPair('ES256')
t.context .intercept({ path: '/jwks-refetch-off-cooldown', method: 'GET', }) .reply(200, { keys: [ { ...(await jose.exportJWK(key.publicKey)), kid: 'foo', }, ], })
const as: lib.AuthorizationServer = { ...issuer, jwks_uri: endpoint('jwks-refetch-off-cooldown'), userinfo_signing_alg_values_supported: ['ES256'], } const c: lib.Client = { ...client, }
let jwt = await new jose.SignJWT({ sub: 'subject' }) .setProtectedHeader({ alg: 'ES256', kid: 'foo' }) .sign(key.privateKey)
let response = getResponse(jwt, { headers: new Headers({ 'content-type': 'application/jwt' }) })
await lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response)
jwt = await new jose.SignJWT({ sub: 'subject' }) .setProtectedHeader({ alg: 'ES256', kid: 'foo2' }) .sign(key.privateKey)
response = getResponse(jwt, { headers: new Headers({ 'content-type': 'application/jwt' }) })
t.context .intercept({ path: '/jwks-refetch-off-cooldown', method: 'GET', }) .reply(200, { keys: [ { ...(await jose.exportJWK(key.publicKey)), kid: 'foo2', }, ], })
// re-fetch not allowed yet await t.throwsAsync(() => lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response), { message: 'error when selecting a JWT verification key, no applicable keys found', }) timekeeper.travel(now + 59 * 1000) await t.throwsAsync(() => lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response), { message: 'error when selecting a JWT verification key, no applicable keys found', })
timekeeper.travel(now + 60 * 1000)
await t.notThrowsAsync(() => lib.processUserInfoResponse(as, c, lib.skipSubjectCheck, response))})
oauth4webapi

Version Info

Tagged at
2 years ago