UNPKG

jwks-client

Version:

Library to retrieve public keys from a JWKS endpoint

99 lines (81 loc) 2.59 kB
import debug from 'debug'; import fetch from 'node-fetch'; import JwkToPem from 'jwk-to-pem'; import JwksError from './lib/errors/JwksError.js'; import SigningKeyNotFoundError from './lib/errors/SigningKeyNotFoundError.js'; import rateLimitSigningKey from './lib/wrappers/rateLimit.js'; import cacheSigningKey from './lib/wrappers/cache.js'; const logger = debug('jwks'); export default class JwksClient { constructor(options) { this.options = Object.assign({ rateLimit: false, cache: false, headers: {} }, options); let _this = this; this.getSigningKey = function(kid, cb) { logger(`Fetching signing key for '${kid}'`); _this.getSigningKeys((err, keys) => { if (err) { return cb(err); } const key = keys.find(k => k.kid === kid); if (key) { return cb(null, key); } else { logger(`Unable to find a signing key that matches '${kid}'`); return cb(new SigningKeyNotFoundError(`Unable to find a signing key that matches '${kid}'`)); } }); }; // Initialize wrappers. if (this.options.rateLimit) { this.getSigningKey = rateLimitSigningKey(this, options); } if (this.options.cache) { this.getSigningKey = cacheSigningKey(this, options); } } async getKeys(cb) { logger(`Fetching keys from '${this.options.jwksUri}'`); try { const response = await fetch(this.options.jwksUri, { headers: this.options.headers }); let data = await response.text(); if(!response.ok) { logger('Failure:', response); return cb(new JwksError(data.message || data)); } else { data = JSON.parse(data); } logger('Keys:', data.keys); return cb(null, data.keys); } catch( error ) { cb(error); } } getSigningKeys(cb) { this.getKeys((err, keys) => { if (err) { return cb(err); } if (!keys || !keys.length) { return cb(new JwksError('The JWKS endpoint did not contain any keys')); } const signingKeys = keys.filter(key => { return key.use === 'sig' && key.kid; }).map(key => { let publicKey = JwkToPem(key); let result = { kid: key.kid, nbf: key.nbf, publicKey: publicKey }; return result; }); if (!signingKeys.length) { return cb(new JwksError('The JWKS endpoint did not contain any signing keys')); } logger('Signing Keys:', signingKeys); return cb(null, signingKeys); }); } }