UNPKG

21.4 kBJavaScriptView Raw
1import nock from 'nock';
2import { expect } from 'chai';
3
4import { x5cMultiple } from './keys';
5import { JwksClient } from '../src/JwksClient';
6
7describe('JwksClient', () => {
8 const jwksHost = 'http://my-authz-server';
9 const proxy = 'my-proxy-server:2815';
10
11 beforeEach(() => {
12 nock.cleanAll();
13 });
14
15 describe('#getKeys', () => {
16 it('should handle errors', done => {
17 nock(jwksHost)
18 .get('/.well-known/jwks.json')
19 .reply(500, 'Unknown Server Error');
20
21 const client = new JwksClient({
22 jwksUri: `${jwksHost}/.well-known/jwks.json`
23 });
24
25 client.getKeys(err => {
26 expect(err).not.to.be.null;
27 expect(err.message).to.equal('Unknown Server Error');
28 done();
29 });
30 });
31
32 it('should return keys', done => {
33 nock(jwksHost)
34 .get('/.well-known/jwks.json')
35 .reply(200, {
36 keys: [
37 {
38 alg: 'RS256',
39 kty: 'RSA',
40 use: 'sig',
41 x5c: [ 'pk1' ],
42 kid: 'ABC'
43 },
44 {
45 alg: 'RS256',
46 kty: 'RSA',
47 use: 'sig',
48 x5c: [],
49 kid: '123'
50 }
51 ]
52 });
53
54 const client = new JwksClient({
55 jwksUri: `${jwksHost}/.well-known/jwks.json`
56 });
57
58 client.getKeys((err, keys) => {
59 expect(err).to.be.null;
60 expect(keys).not.to.be.null;
61 expect(keys.length).to.equal(2);
62 expect(keys[1].kid).to.equal('123');
63 done();
64 });
65 });
66
67 it('should set request agentOptions when provided', done => {
68 nock(jwksHost)
69 .get('./well-known/jwks.json')
70 .reply(function() {
71 expect(this.req.agentOptions).not.to.be.null;
72 expect(this.req.agentOptions['ca']).to.be.equal('loadCA()');
73 return 200;
74 });
75
76 const client = new JwksClient({
77 jwksUri: `${jwksHost}/.well-known/jwks.json`,
78 requestAgentOptions: {
79 ca: 'loadCA()'
80 }
81 });
82
83 client.getKeys(() => {
84 done();
85 });
86 });
87
88 it('should not set request agentOptions by default', done => {
89 nock(jwksHost)
90 .get('/.well-known/jwks.json')
91 .reply(function() {
92 expect(this.req).to.not.have.property('agentOptions');
93 return 200;
94 });
95
96 const client = new JwksClient({
97 jwksUri: `${jwksHost}/.well-known/jwks.json`
98 });
99
100 client.getKeys(() => {
101 done();
102 });
103 });
104
105 it('should send extra header', done => {
106 nock(jwksHost)
107 .get('/.well-known/jwks.json')
108 .reply(function() {
109 expect(this.req.headers).not.to.be.null;
110 expect(this.req.headers['user-agent']).to.be.equal('My-bot');
111 expect(Object.keys(this.req.headers).length).to.be.equal(3);
112 return (
113 200,
114 {
115 keys: [
116 {
117 alg: 'RS256',
118 kty: 'RSA',
119 use: 'sig',
120 x5c: [ 'pk1' ],
121 kid: 'ABC'
122 },
123 {
124 alg: 'RS256',
125 kty: 'RSA',
126 use: 'sig',
127 x5c: [],
128 kid: '123'
129 }
130 ]
131 }
132 );
133 });
134
135 const client = new JwksClient({
136 jwksUri: `${jwksHost}/.well-known/jwks.json`,
137 requestHeaders: {
138 'User-Agent': 'My-bot'
139 }
140 });
141
142 client.getKeys(() => {
143 done();
144 });
145 });
146
147 it('should not send the extra headers when not provided', done => {
148 nock(jwksHost)
149 .get('/.well-known/jwks.json')
150 .reply(function() {
151 expect(this.req.headers).not.to.be.null;
152 expect(this.req.headers['accept']).not.to.be.undefined;
153 expect(this.req.headers['host']).not.to.be.undefined;
154 expect(Object.keys(this.req.headers).length).to.be.equal(2);
155 return (
156 200,
157 {
158 keys: [
159 {
160 alg: 'RS256',
161 kty: 'RSA',
162 use: 'sig',
163 x5c: [ 'pk1' ],
164 kid: 'ABC'
165 },
166 {
167 alg: 'RS256',
168 kty: 'RSA',
169 use: 'sig',
170 x5c: [],
171 kid: '123'
172 }
173 ]
174 }
175 );
176 });
177
178 const client = new JwksClient({
179 jwksUri: `${jwksHost}/.well-known/jwks.json`
180 });
181
182 client.getKeys(() => {
183 done();
184 });
185 });
186
187 it('should use a proxy if specified', done => {
188 const expectedError = { message: 'expectedError' };
189 nock(`http://${proxy}`)
190 .get(() => true)
191 .replyWithError(expectedError);
192
193 const client = new JwksClient({
194 jwksUri: `${jwksHost}/.well-known/jwks.json`,
195 requestHeaders: {
196 'User-Agent': 'My-bot'
197 },
198 proxy: `http://username:password@${proxy}`
199 });
200
201 client.getKeys((err) => {
202 expect(err).to.equal(expectedError);
203 done();
204 });
205 });
206 });
207
208 describe('#getSigningKeys', () => {
209 it('should handle errors', done => {
210 nock(jwksHost)
211 .get('/.well-known/jwks.json')
212 .reply(500, 'Unknown Server Error');
213
214 const client = new JwksClient({
215 jwksUri: `${jwksHost}/.well-known/jwks.json`
216 });
217
218 client.getSigningKeys(err => {
219 expect(err).not.to.be.null;
220 expect(err.message).to.equal('Unknown Server Error');
221 done();
222 });
223 });
224
225 it('should return signing keys (with x5c and mod/exp)', done => {
226 nock(jwksHost)
227 .get('/.well-known/jwks.json')
228 .reply(200, {
229 keys: [
230 {
231 alg: 'RS256',
232 kty: 'RSA',
233 use: 'sig',
234 x5c: [
235 'MIIDDTCCAfWgAwIBAgIJAJVkuSv2H8mDMA0GCSqGSIb3DQEBBQUAMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTAeFw0xNDA1MTQyMTIyMjZaFw0yODAxMjEyMTIyMjZaMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6jWASkHhXz5Ug6t5BsYBrXDIgrWu05f3oq2fE+5J5REKJiY0Ddc+Kda34ZwOptnUoef3JwKPDAckTJQDugweNNZPwOmFMRKj4xqEpxEkIX8C+zHs41Q6x54ZZy0xU+WvTGcdjzyZTZ/h0iOYisswFQT/s6750tZG0BOBtZ5qS/80tmWH7xFitgewdWteJaASE/eO1qMtdNsp9fxOtN5U/pZDUyFm3YRfOcODzVqp3wOz+dcKb7cdZN11EYGZOkjEekpcedzHCo9H4aOmdKCpytqL/9FXoihcBMg39s1OW3cfwfgf5/kvOJdcqR4PoATQTfsDVoeMWVB4XLGR6SC5kCAwEAAaNQME4wHQYDVR0OBBYEFHDYn9BQdup1CoeoFi0Rmf5xn/W9MB8GA1UdIwQYMBaAFHDYn9BQdup1CoeoFi0Rmf5xn/W9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGLpQZdd2ICVnGjc6CYfT3VNoujKYWk7E0shGaCXFXptrZ8yaryfo6WAizTfgOpQNJH+Jz+QsCjvkRt6PBSYX/hb5OUDU2zNJN48/VOw57nzWdjI70H2Ar4oJLck36xkIRs/+QX+mSNCjZboRwh0LxanXeALHSbCgJkbzWbjVnfJEQUP9P/7NGf0MkO5I95C/Pz9g91y8gU+R3imGppLy9Zx+OwADFwKAEJak4JrNgcjHBQenakAXnXP6HG4hHH4MzO8LnLiKv8ZkKVL67da/80PcpO0miMNPaqBBMd2Cy6GzQYE0ag6k0nk+DMIFn7K+o21gjUuOEJqIbAvhbf2KcM='
236 ],
237 n:
238 'vqNYBKQeFfPlSDq3kGxgGtcMiCta7Tl_eirZ8T7knlEQomJjQN1z4p1rfhnA6m2dSh5_cnAo8MByRMlAO6DB401k_A6YUxEqPjGoSnESQhfwL7MezjVDrHnhlnLTFT5a9MZx2PPJlNn-HSI5iKyzAVBP-zrvnS1kbQE4G1nmpL_zS2ZYfvEWK2B7B1a14loBIT947Woy102yn1_E603lT-lkNTIWbdhF85w4PNWqnfA7P51wpvtx1k3XURgZk6SMR6Slx53McKj0fho6Z0oKnK2ov_0VeiKFwEyDf2zU5bdx_B-B_n-S84l1ypHg-gBNBN-wNWh4xZUHhcsZHpILmQ',
239 e: 'AQAB',
240 kid: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg',
241 x5t: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'
242 },
243 {
244 kid: 'IdTokenSigningKeyContainer',
245 use: 'sig',
246 kty: 'RSA',
247 e: 'AQAB',
248 n:
249 'tLDZVZ2Eq_DFwNp24yeSq_Ha0MYbYOJs_WXIgVxQGabu5cZ9561OUtYWdB6xXXZLaZxFG02P5U2rC_CT1r0lPfC_KHYrviJ5Y_Ekif7iFV_1omLAiRksQziwA1i-hND32N5kxwEGNmZViVjWMBZ43wbIdWss4IMhrJy1WNQ07Fqp1Ee6o7QM1hTBve7bbkJkUAfjtC7mwIWqZdWoYIWBTZRXvhMgs_Aeb_pnDekosqDoWQ5aMklk3NvaaBBESqlRAJZUUf5WDFoJh7yRELOFF4lWJxtArTEiQPWVTX6PCs0klVPU6SRQqrtc4kKLCp1AC5EJqPYRGiEJpSz2nUhmAQ'
250 }
251 ]
252 });
253
254 const client = new JwksClient({
255 jwksUri: `${jwksHost}/.well-known/jwks.json`
256 });
257
258 client.getSigningKeys((err, keys) => {
259 expect(err).to.be.null;
260 expect(keys).not.to.be.null;
261 expect(keys.length).to.equal(2);
262 const pubkey0 = keys[0].publicKey || keys[0].rsaPublicKey;
263 expect(pubkey0).not.to.be.null;
264 expect(keys[0].getPublicKey()).to.equal(keys[0].publicKey);
265 expect(keys[1].kid).to.equal('IdTokenSigningKeyContainer');
266 expect(keys[0].kid).to.equal('RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg');
267 const pubkey1 = keys[1].publicKey || keys[1].rsaPublicKey;
268 expect(pubkey1).not.to.be.null;
269 expect(keys[1].getPublicKey()).to.equal(keys[1].rsaPublicKey);
270 done();
271 });
272 });
273
274 it('should return signing keys (with x5c)', done => {
275 nock(jwksHost)
276 .get('/.well-known/jwks.json')
277 .reply(200, {
278 keys: [
279 {
280 alg: 'RS256',
281 kty: 'RSA',
282 use: 'sig',
283 x5c: [
284 'MIIDDTCCAfWgAwIBAgIJAJVkuSv2H8mDMA0GCSqGSIb3DQEBBQUAMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTAeFw0xNDA1MTQyMTIyMjZaFw0yODAxMjEyMTIyMjZaMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6jWASkHhXz5Ug6t5BsYBrXDIgrWu05f3oq2fE+5J5REKJiY0Ddc+Kda34ZwOptnUoef3JwKPDAckTJQDugweNNZPwOmFMRKj4xqEpxEkIX8C+zHs41Q6x54ZZy0xU+WvTGcdjzyZTZ/h0iOYisswFQT/s6750tZG0BOBtZ5qS/80tmWH7xFitgewdWteJaASE/eO1qMtdNsp9fxOtN5U/pZDUyFm3YRfOcODzVqp3wOz+dcKb7cdZN11EYGZOkjEekpcedzHCo9H4aOmdKCpytqL/9FXoihcBMg39s1OW3cfwfgf5/kvOJdcqR4PoATQTfsDVoeMWVB4XLGR6SC5kCAwEAAaNQME4wHQYDVR0OBBYEFHDYn9BQdup1CoeoFi0Rmf5xn/W9MB8GA1UdIwQYMBaAFHDYn9BQdup1CoeoFi0Rmf5xn/W9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGLpQZdd2ICVnGjc6CYfT3VNoujKYWk7E0shGaCXFXptrZ8yaryfo6WAizTfgOpQNJH+Jz+QsCjvkRt6PBSYX/hb5OUDU2zNJN48/VOw57nzWdjI70H2Ar4oJLck36xkIRs/+QX+mSNCjZboRwh0LxanXeALHSbCgJkbzWbjVnfJEQUP9P/7NGf0MkO5I95C/Pz9g91y8gU+R3imGppLy9Zx+OwADFwKAEJak4JrNgcjHBQenakAXnXP6HG4hHH4MzO8LnLiKv8ZkKVL67da/80PcpO0miMNPaqBBMd2Cy6GzQYE0ag6k0nk+DMIFn7K+o21gjUuOEJqIbAvhbf2KcM='
285 ],
286 n:
287 'vqNYBKQeFfPlSDq3kGxgGtcMiCta7Tl_eirZ8T7knlEQomJjQN1z4p1rfhnA6m2dSh5_cnAo8MByRMlAO6DB401k_A6YUxEqPjGoSnESQhfwL7MezjVDrHnhlnLTFT5a9MZx2PPJlNn-HSI5iKyzAVBP-zrvnS1kbQE4G1nmpL_zS2ZYfvEWK2B7B1a14loBIT947Woy102yn1_E603lT-lkNTIWbdhF85w4PNWqnfA7P51wpvtx1k3XURgZk6SMR6Slx53McKj0fho6Z0oKnK2ov_0VeiKFwEyDf2zU5bdx_B-B_n-S84l1ypHg-gBNBN-wNWh4xZUHhcsZHpILmQ',
288 e: 'AQAB',
289 kid: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg',
290 x5t: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'
291 },
292 {
293 alg: 'RS256',
294 kty: 'RSA',
295 use: 'sig',
296 nbf: 123,
297 x5c: [
298 'MIIDGzCCAgOgAwIBAgIJAPQM5+PwmOcPMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGXNhbmRyaW5vLWRldi5ldS5hdXRoMC5jb20wHhcNMTUwMzMxMDkwNTQ3WhcNMjgxMjA3MDkwNTQ3WjAkMSIwIAYDVQQDDBlzYW5kcmluby1kZXYuZXUuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv/SECtT7H4rxKtX2HpGhSyeYTe3Vet8YQpjBAr+1TnQ1fcYfvfmnVRHvhmTwABktD1erF1lxFsrRw92yBDOHlL7lj1n2fcfLftSoStgvRHVg52kR+CkBVQ6/mF1lYkefIjik6YRMf55Eu4FqDyVG2dgd5EA8kNO4J8OPc7vAtZyXrRYOZjVXbEgyjje/V+OpMQxAHP2Er11TLuzJjioP0ICVqhAZdq2sLk7agoxn64md6fqOk4N+7lJkU4+412VD0qYwKxD7nGsEclYawKoZD9/xhCk2qfQ/HptIumrdQ5ox3Sq5t2a7VKa41dBUQ1MQtXG2iY7S9RlfcMIyQwGhOQIDAQABo1AwTjAdBgNVHQ4EFgQUHpS1fvO/54G2c1VpEDNUZRSl44gwHwYDVR0jBBgwFoAUHpS1fvO/54G2c1VpEDNUZRSl44gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAtm9I0nr6eXF5aq4yllfiqZcQ6mKrJLH9Rm4Jv+olniNynTcnpwprRVLToIawc8MmzIGZTtCn7u+dSxWf1UNE+SH7XgEnGtO74239vleEx1+Tf5viIdsnCxgvFiPdOqRlc9KcFSWd6a7RzcglnyU7GEx0K5GLv1wPA6qEM+3uwNwjAyVSu5dFw8kCfaSvlk5rXKRUzSoW9NVomw6+tADR8vMZS+4KThZ+4GH0rMN4KjIaRFxW8OMVYOn12uq33fLCd6MuPHW/rklxLbQBoHIU/ClNhbD0t6f00w9lHhPy4IP73rv7Oow0Ny6i70Iq0ijqj+kAtnrphlOvLFxqn6nCvQ=='
299 ],
300 n:
301 'v_SECtT7H4rxKtX2HpGhSyeYTe3Vet8YQpjBAr-1TnQ1fcYfvfmnVRHvhmTwABktD1erF1lxFsrRw92yBDOHlL7lj1n2fcfLftSoStgvRHVg52kR-CkBVQ6_mF1lYkefIjik6YRMf55Eu4FqDyVG2dgd5EA8kNO4J8OPc7vAtZyXrRYOZjVXbEgyjje_V-OpMQxAHP2Er11TLuzJjioP0ICVqhAZdq2sLk7agoxn64md6fqOk4N-7lJkU4-412VD0qYwKxD7nGsEclYawKoZD9_xhCk2qfQ_HptIumrdQ5ox3Sq5t2a7VKa41dBUQ1MQtXG2iY7S9RlfcMIyQwGhOQ',
302 e: 'AQAB',
303 kid: 'NkFCNEE1NDFDNTQ5RTQ5OTE1QzRBMjYyMzY0NEJCQTJBMjJBQkZCMA',
304 x5t: 'NkFCNEE1NDFDNTQ5RTQ5OTE1QzRBMjYyMzY0NEJCQTJBMjJBQkZCMA'
305 }
306 ]
307 });
308
309 const client = new JwksClient({
310 jwksUri: `${jwksHost}/.well-known/jwks.json`
311 });
312
313 client.getSigningKeys((err, keys) => {
314 expect(err).to.be.null;
315 expect(keys).not.to.be.null;
316 expect(keys.length).to.equal(2);
317 expect(keys[0].publicKey).not.to.be.null;
318 expect(keys[0].getPublicKey()).to.equal(keys[0].publicKey);
319 expect(keys[0].kid).to.equal(
320 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'
321 );
322 expect(keys[1].kid).to.equal(
323 'NkFCNEE1NDFDNTQ5RTQ5OTE1QzRBMjYyMzY0NEJCQTJBMjJBQkZCMA'
324 );
325 expect(keys[1].publicKey).not.to.be.null;
326 expect(keys[1].getPublicKey()).to.equal(keys[1].publicKey);
327 expect(keys[1].nbf).to.equal(123);
328 done();
329 });
330 });
331
332 it('should return signing keys (mod/exp)', done => {
333 nock(jwksHost)
334 .get('/.well-known/jwks.json')
335 .reply(200, {
336 keys: [
337 {
338 kid: 'IdTokenSigningKeyContainer',
339 use: 'sig',
340 kty: 'RSA',
341 e: 'AQAB',
342 n:
343 'tLDZVZ2Eq_DFwNp24yeSq_Ha0MYbYOJs_WXIgVxQGabu5cZ9561OUtYWdB6xXXZLaZxFG02P5U2rC_CT1r0lPfC_KHYrviJ5Y_Ekif7iFV_1omLAiRksQziwA1i-hND32N5kxwEGNmZViVjWMBZ43wbIdWss4IMhrJy1WNQ07Fqp1Ee6o7QM1hTBve7bbkJkUAfjtC7mwIWqZdWoYIWBTZRXvhMgs_Aeb_pnDekosqDoWQ5aMklk3NvaaBBESqlRAJZUUf5WDFoJh7yRELOFF4lWJxtArTEiQPWVTX6PCs0klVPU6SRQqrtc4kKLCp1AC5EJqPYRGiEJpSz2nUhmAQ'
344 },
345 {
346 kid: 'IdTokenSigningKeyContainer.v2',
347 nbf: 1459289287,
348 use: 'sig',
349 kty: 'RSA',
350 e: 'AQAB',
351 n:
352 's4W7xjkQZP3OwG7PfRgcYKn8eRYXHiz1iK503fS-K2FZo-Ublwwa2xFZWpsUU_jtoVCwIkaqZuo6xoKtlMYXXvfVHGuKBHEBVn8b8x_57BQWz1d0KdrNXxuMvtFe6RzMqiMqzqZrzae4UqVCkYqcR9gQx66Ehq7hPmCxJCkg7ajo7fu6E7dPd34KH2HSYRsaaEA_BcKTeb9H1XE_qEKjog68wUU9Ekfl3FBIRN-1Ah_BoktGFoXyi_jt0-L0-gKcL1BLmUlGzMusvRbjI_0-qj-mc0utGdRjY-xIN2yBj8vl4DODO-wMwfp-cqZbCd9TENyHaTb8iA27s-73L3ExOQ'
353 },
354 {
355 kid: 'IdTokenSigningKeyContainer.v3',
356 nbf: 1459289287,
357 kty: 'RSA',
358 e: 'AQAB',
359 n:
360 's4W7xjkQZP3OwG7PfRgcYKn8eRYXHiz1iK503fS-K2FZo-Ublwwa2xFZWpsUU_jtoVCwIkaqZuo6xoKtlMYXXvfVHGuKBHEBVn8b8x_57BQWz1d0KdrNXxuMvtFe6RzMqiMqzqZrzae4UqVCkYqcR9gQx66Ehq7hPmCxJCkg7ajo7fu6E7dPd34KH2HSYRsaaEA_BcKTeb9H1XE_qEKjog68wUU9Ekfl3FBIRN-1Ah_BoktGFoXyi_jt0-L0-gKcL1BLmUlGzMusvRbjI_0-qj-mc0utGdRjY-xIN2yBj8vl4DODO-wMwfp-cqZbCd9TENyHaTb8iA27s-73L3ExOQ'
361 },
362 {
363 kid: 'IdTokenSigningKeyContainer.v4',
364 nbf: 1459289287,
365 use: 'enc',
366 kty: 'RSA',
367 e: 'AQAB',
368 n:
369 's4W7xjkQZP3OwG7PfRgcYKn8eRYXHiz1iK503fS-K2FZo-Ublwwa2xFZWpsUU_jtoVCwIkaqZuo6xoKtlMYXXvfVHGuKBHEBVn8b8x_57BQWz1d0KdrNXxuMvtFe6RzMqiMqzqZrzae4UqVCkYqcR9gQx66Ehq7hPmCxJCkg7ajo7fu6E7dPd34KH2HSYRsaaEA_BcKTeb9H1XE_qEKjog68wUU9Ekfl3FBIRN-1Ah_BoktGFoXyi_jt0-L0-gKcL1BLmUlGzMusvRbjI_0-qj-mc0utGdRjY-xIN2yBj8vl4DODO-wMwfp-cqZbCd9TENyHaTb8iA27s-73L3ExOQ'
370 }
371 ]
372 });
373
374 const client = new JwksClient({
375 jwksUri: `${jwksHost}/.well-known/jwks.json`
376 });
377
378 client.getSigningKeys((err, keys) => {
379 expect(err).to.be.null;
380 expect(keys).not.to.be.null;
381 expect(keys.length).to.equal(3);
382 expect(keys[0].rsaPublicKey).not.to.be.null;
383 expect(keys[0].getPublicKey()).to.equal(keys[0].rsaPublicKey);
384 expect(keys[0].kid).to.equal('IdTokenSigningKeyContainer');
385 expect(keys[1].kid).to.equal('IdTokenSigningKeyContainer.v2');
386 expect(keys[1].rsaPublicKey).not.to.be.null;
387 expect(keys[1].getPublicKey()).to.equal(keys[1].rsaPublicKey);
388 expect(keys[1].nbf).to.equal(1459289287);
389 expect(keys[2].rsaPublicKey).not.to.be.null;
390 expect(keys[2].getPublicKey()).to.equal(keys[2].rsaPublicKey);
391 done();
392 });
393 });
394
395 it('should only take the signing keys from the keys', done => {
396 nock(jwksHost)
397 .get('/.well-known/jwks.json')
398 .reply(200, {
399 keys: [
400 {
401 kty: 'something',
402 use: 'else',
403 x5c: [
404 'MIIDDTCCAfWgAwIBAgIJAJVkuSv2H8mDMA0GCSqGSIb3DQEBBQUAMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTAeFw0xNDA1MTQyMTIyMjZaFw0yODAxMjEyMTIyMjZaMB0xGzAZBgNVBAMMEnNhbmRyaW5vLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6jWASkHhXz5Ug6t5BsYBrXDIgrWu05f3oq2fE+5J5REKJiY0Ddc+Kda34ZwOptnUoef3JwKPDAckTJQDugweNNZPwOmFMRKj4xqEpxEkIX8C+zHs41Q6x54ZZy0xU+WvTGcdjzyZTZ/h0iOYisswFQT/s6750tZG0BOBtZ5qS/80tmWH7xFitgewdWteJaASE/eO1qMtdNsp9fxOtN5U/pZDUyFm3YRfOcODzVqp3wOz+dcKb7cdZN11EYGZOkjEekpcedzHCo9H4aOmdKCpytqL/9FXoihcBMg39s1OW3cfwfgf5/kvOJdcqR4PoATQTfsDVoeMWVB4XLGR6SC5kCAwEAAaNQME4wHQYDVR0OBBYEFHDYn9BQdup1CoeoFi0Rmf5xn/W9MB8GA1UdIwQYMBaAFHDYn9BQdup1CoeoFi0Rmf5xn/W9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGLpQZdd2ICVnGjc6CYfT3VNoujKYWk7E0shGaCXFXptrZ8yaryfo6WAizTfgOpQNJH+Jz+QsCjvkRt6PBSYX/hb5OUDU2zNJN48/VOw57nzWdjI70H2Ar4oJLck36xkIRs/+QX+mSNCjZboRwh0LxanXeALHSbCgJkbzWbjVnfJEQUP9P/7NGf0MkO5I95C/Pz9g91y8gU+R3imGppLy9Zx+OwADFwKAEJak4JrNgcjHBQenakAXnXP6HG4hHH4MzO8LnLiKv8ZkKVL67da/80PcpO0miMNPaqBBMd2Cy6GzQYE0ag6k0nk+DMIFn7K+o21gjUuOEJqIbAvhbf2KcM='
405 ],
406 n:
407 'vqNYBKQeFfPlSDq3kGxgGtcMiCta7Tl_eirZ8T7knlEQomJjQN1z4p1rfhnA6m2dSh5_cnAo8MByRMlAO6DB401k_A6YUxEqPjGoSnESQhfwL7MezjVDrHnhlnLTFT5a9MZx2PPJlNn-HSI5iKyzAVBP-zrvnS1kbQE4G1nmpL_zS2ZYfvEWK2B7B1a14loBIT947Woy102yn1_E603lT-lkNTIWbdhF85w4PNWqnfA7P51wpvtx1k3XURgZk6SMR6Slx53McKj0fho6Z0oKnK2ov_0VeiKFwEyDf2zU5bdx_B-B_n-S84l1ypHg-gBNBN-wNWh4xZUHhcsZHpILmQ',
408 e: 'AQAB',
409 kid: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg',
410 x5t: 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'
411 },
412 {
413 kty: 'something',
414 use: 'else',
415 nbf: 123,
416 x5c: [
417 'MIIDGzCCAgOgAwIBAgIJAPQM5+PwmOcPMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNVBAMMGXNhbmRyaW5vLWRldi5ldS5hdXRoMC5jb20wHhcNMTUwMzMxMDkwNTQ3WhcNMjgxMjA3MDkwNTQ3WjAkMSIwIAYDVQQDDBlzYW5kcmluby1kZXYuZXUuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv/SECtT7H4rxKtX2HpGhSyeYTe3Vet8YQpjBAr+1TnQ1fcYfvfmnVRHvhmTwABktD1erF1lxFsrRw92yBDOHlL7lj1n2fcfLftSoStgvRHVg52kR+CkBVQ6/mF1lYkefIjik6YRMf55Eu4FqDyVG2dgd5EA8kNO4J8OPc7vAtZyXrRYOZjVXbEgyjje/V+OpMQxAHP2Er11TLuzJjioP0ICVqhAZdq2sLk7agoxn64md6fqOk4N+7lJkU4+412VD0qYwKxD7nGsEclYawKoZD9/xhCk2qfQ/HptIumrdQ5ox3Sq5t2a7VKa41dBUQ1MQtXG2iY7S9RlfcMIyQwGhOQIDAQABo1AwTjAdBgNVHQ4EFgQUHpS1fvO/54G2c1VpEDNUZRSl44gwHwYDVR0jBBgwFoAUHpS1fvO/54G2c1VpEDNUZRSl44gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAtm9I0nr6eXF5aq4yllfiqZcQ6mKrJLH9Rm4Jv+olniNynTcnpwprRVLToIawc8MmzIGZTtCn7u+dSxWf1UNE+SH7XgEnGtO74239vleEx1+Tf5viIdsnCxgvFiPdOqRlc9KcFSWd6a7RzcglnyU7GEx0K5GLv1wPA6qEM+3uwNwjAyVSu5dFw8kCfaSvlk5rXKRUzSoW9NVomw6+tADR8vMZS+4KThZ+4GH0rMN4KjIaRFxW8OMVYOn12uq33fLCd6MuPHW/rklxLbQBoHIU/ClNhbD0t6f00w9lHhPy4IP73rv7Oow0Ny6i70Iq0ijqj+kAtnrphlOvLFxqn6nCvQ=='
418 ],
419 n:
420 'v_SECtT7H4rxKtX2HpGhSyeYTe3Vet8YQpjBAr-1TnQ1fcYfvfmnVRHvhmTwABktD1erF1lxFsrRw92yBDOHlL7lj1n2fcfLftSoStgvRHVg52kR-CkBVQ6_mF1lYkefIjik6YRMf55Eu4FqDyVG2dgd5EA8kNO4J8OPc7vAtZyXrRYOZjVXbEgyjje_V-OpMQxAHP2Er11TLuzJjioP0ICVqhAZdq2sLk7agoxn64md6fqOk4N-7lJkU4-412VD0qYwKxD7nGsEclYawKoZD9_xhCk2qfQ_HptIumrdQ5ox3Sq5t2a7VKa41dBUQ1MQtXG2iY7S9RlfcMIyQwGhOQ',
421 e: 'AQAB',
422 kid: 'NkFCNEE1NDFDNTQ5RTQ5OTE1QzRBMjYyMzY0NEJCQTJBMjJBQkZCMA',
423 x5t: 'NkFCNEE1NDFDNTQ5RTQ5OTE1QzRBMjYyMzY0NEJCQTJBMjJBQkZCMA'
424 }
425 ]
426 });
427
428 const client = new JwksClient({
429 jwksUri: `${jwksHost}/.well-known/jwks.json`
430 });
431
432 client.getSigningKeys(err => {
433 expect(err).not.to.be.null;
434 expect(err.name).to.equal('JwksError');
435 expect(err.message).to.equal(
436 'The JWKS endpoint did not contain any signing keys'
437 );
438 done();
439 });
440 });
441 });
442
443 describe('#getSigningKey', () => {
444 it('should return error if signing key is not found', done => {
445 nock(jwksHost)
446 .get('/.well-known/jwks.json')
447 .reply(200, x5cMultiple);
448
449 const client = new JwksClient({
450 jwksUri: `${jwksHost}/.well-known/jwks.json`
451 });
452
453 client.getSigningKey('1234', err => {
454 expect(err).not.to.be.null;
455 expect(err.name).to.equal('SigningKeyNotFoundError');
456 done();
457 });
458 });
459 });
460});