fetch_jwks.js 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import * as http from 'http';
  2. import * as https from 'https';
  3. import { once } from 'events';
  4. import { JOSEError, JWKSTimeout } from '../util/errors.js';
  5. import { concat, decoder } from '../lib/buffer_utils.js';
  6. const fetchJwks = async (url, timeout, options) => {
  7. let get;
  8. switch (url.protocol) {
  9. case 'https:':
  10. get = https.get;
  11. break;
  12. case 'http:':
  13. get = http.get;
  14. break;
  15. default:
  16. throw new TypeError('Unsupported URL protocol.');
  17. }
  18. const { agent, headers } = options;
  19. const req = get(url.href, {
  20. agent,
  21. timeout,
  22. headers,
  23. });
  24. const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')]));
  25. if (!response) {
  26. req.destroy();
  27. throw new JWKSTimeout();
  28. }
  29. if (response.statusCode !== 200) {
  30. throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');
  31. }
  32. const parts = [];
  33. for await (const part of response) {
  34. parts.push(part);
  35. }
  36. try {
  37. return JSON.parse(decoder.decode(concat(...parts)));
  38. }
  39. catch {
  40. throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON');
  41. }
  42. };
  43. export default fetchJwks;