This commit is contained in:
girinb
2025-05-29 15:41:51 +09:00
parent a1bd4f87a1
commit 485098cd1a
5611 changed files with 881685 additions and 0 deletions

21
node_modules/jwks-rsa/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Sandrino Di Mattia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

83
node_modules/jwks-rsa/README.md generated vendored Normal file
View File

@@ -0,0 +1,83 @@
![A library to retrieve signing keys from a JWKS (JSON Web Key Set) endpoint.](https://cdn.auth0.com/website/sdks/banner/node-jwks-rsa-banner.png)
![Release](https://img.shields.io/npm/v/jwks-rsa)
[![Codecov](https://img.shields.io/codecov/c/github/auth0/node-jwks-rsa)](https://codecov.io/gh/auth0/node-jwks-rsa)
![Downloads](https://img.shields.io/npm/dw/jwks-rsa)
[![License](https://img.shields.io/:license-mit-blue.svg?style=flat)](https://opensource.org/licenses/MIT)
![CircleCI](https://img.shields.io/circleci/build/github/auth0/node-jwks-rsa)
📚 [Documentation](#documentation) - 🚀 [Getting Started](#getting-started) - 💬 [Feedback](#feedback)
## Documentation
- [Examples](https://github.com/auth0/node-jwks-rsa/blob/master/EXAMPLES.md) - documentation of the options and code samples for common scenarios.
- [Docs Site](https://auth0.com/docs) - explore our Docs site and learn more about Auth0.
## Getting Started
### Installation
Using [npm](https://npmjs.org) in your project directory run the following command:
````bash
npm install --save jwks-rsa
````
Supports all currently registered JWK types and JWS Algorithms, see [panva/jose#262](https://github.com/panva/jose/issues/262) for more information.
### Configure the client
Provide a JWKS endpoint which exposes your signing keys.
````js
const jwksClient = require('jwks-rsa');
const client = jwksClient({
jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json',
requestHeaders: {}, // Optional
timeout: 30000 // Defaults to 30s
});
````
### Retrieve a key
Then use `getSigningKey` to retrieve a signing key that matches a specific `kid`.
````js
const kid = 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg';
const key = await client.getSigningKey(kid);
const signingKey = key.getPublicKey();
````
## Feedback
### Contributing
We appreciate feedback and contribution to this repo! Before you get started, please see the following:
- [Auth0's general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md)
- [Auth0's code of conduct guidelines](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md)
### Raise an issue
To provide feedback or report a bug, please [raise an issue on our issue tracker](https://github.com/auth0/node-jwks-rsa/issues).
### Vulnerability Reporting
Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.
## What is Auth0?
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_dark_mode.png" width="150">
<source media="(prefers-color-scheme: light)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
<img alt="Auth0 Logo" src="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
</picture>
</p>
<p align="center">
Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout <a href="https://auth0.com/why-auth0">Why Auth0?</a>
</p>
<p align="center">
This project is licensed under the MIT license. See the <a href="https://github.com/auth0/node-jwks-rsa/blob/master/LICENSE"> LICENSE</a> file for more info.
</p>

130
node_modules/jwks-rsa/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,130 @@
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';
import type {Jwt, Secret} from 'jsonwebtoken'
import Express = require('express')
declare function JwksRsa(options: JwksRsa.Options): JwksRsa.JwksClient;
declare namespace JwksRsa {
class JwksClient {
constructor(options: Options);
getKeys(): Promise<unknown>;
getSigningKeys(): Promise<SigningKey[]>;
getSigningKey(kid?: string | null | undefined): Promise<SigningKey>;
getSigningKey(kid: string | null | undefined, cb: (err: Error | null, key?: SigningKey) => void): void;
}
interface Headers {
[key: string]: string;
}
interface Options {
jwksUri: string;
rateLimit?: boolean;
cache?: boolean;
cacheMaxEntries?: number;
cacheMaxAge?: number;
jwksRequestsPerMinute?: number;
proxy?: string;
requestHeaders?: Headers;
timeout?: number;
requestAgent?: HttpAgent | HttpsAgent;
fetcher?(jwksUri: string): Promise<{ keys: any }>;
getKeysInterceptor?(): Promise<JSONWebKey[]>;
}
interface JSONWebKey {
kid: string,
alg: string,
[key: string]: any
}
interface CertSigningKey {
kid: string;
alg: string;
getPublicKey(): string;
publicKey: string;
}
interface RsaSigningKey {
kid: string;
alg: string;
getPublicKey(): string;
rsaPublicKey: string;
}
type SigningKey = CertSigningKey | RsaSigningKey;
/**
* Types are duplicated from express-jwt@6/7
* due to numerous breaking changes in the lib's types
* whilst this lib supportd both <=6 & >=7 implementations
*
* express-jwt's installed version (or its @types)
* will be the types used at transpilation time
*/
/** Types from express-jwt@<=6 */
type secretType = string|Buffer;
type SecretCallbackLong = (req: unknown, header: any, payload: any, done: (err: any, secret?: secretType) => void) => void;
type SecretCallback = (req: unknown, payload: any, done: (err: any, secret?: secretType) => void) => void;
/** Types from express-jwt@>=7 */
type GetVerificationKey = (req: unknown, token: Jwt | undefined) => Secret | undefined | Promise<Secret | undefined>;
function expressJwtSecret(options: ExpressJwtOptions): SecretCallbackLong & GetVerificationKey;
function passportJwtSecret(options: ExpressJwtOptions): SecretCallback;
interface ExpressJwtOptions extends Options {
handleSigningKeyError?: (err: Error | null, cb: (err: Error | null) => void) => void;
}
function hapiJwt2Key(options: HapiJwtOptions): (decodedToken: DecodedToken, cb: HapiCallback) => void;
interface HapiJwtOptions extends Options {
handleSigningKeyError?: (err: Error | null, cb: HapiCallback) => void;
}
type HapiCallback = (err: Error | null, publicKey: string, signingKey: SigningKey) => void;
interface DecodedToken {
header: TokenHeader;
}
interface TokenHeader {
alg: string;
kid: string;
}
function hapiJwt2KeyAsync(options: HapiJwtOptions): (decodedToken: DecodedToken) => Promise<{ key: string }>;
function koaJwtSecret(options: KoaJwtOptions): (header: TokenHeader) => Promise<string>;
interface KoaJwtOptions extends Options {
handleSigningKeyError?(err: Error | null): Promise<void>;
}
class ArgumentError extends Error {
name: 'ArgumentError';
constructor(message: string);
}
class JwksError extends Error {
name: 'JwksError';
constructor(message: string);
}
class JwksRateLimitError extends Error {
name: 'JwksRateLimitError';
constructor(message: string);
}
class SigningKeyNotFoundError extends Error {
name: 'SigningKeyNotFoundError';
constructor(message: string);
}
}
export = JwksRsa;

74
node_modules/jwks-rsa/package.json generated vendored Normal file
View File

@@ -0,0 +1,74 @@
{
"name": "jwks-rsa",
"version": "3.2.0",
"description": "Library to retrieve RSA public keys from a JWKS endpoint",
"main": "src/index.js",
"files": [
"src",
"index.d.ts"
],
"types": "index.d.ts",
"engines": {
"node": ">=14"
},
"dependencies": {
"@types/express": "^4.17.20",
"@types/jsonwebtoken": "^9.0.4",
"debug": "^4.3.4",
"jose": "^4.15.4",
"limiter": "^1.1.5",
"lru-memoizer": "^2.2.0"
},
"devDependencies": {
"@types/chai": "^4.3.9",
"@types/express-jwt-v6": "npm:@types/express-jwt@^6.0.4",
"@types/mocha": "^10.0.3",
"@types/nock": "^11.0.0",
"@types/node": "^20.8.10",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"eslint": "^8.52.0",
"express": "^4.18.2",
"express-jwt": "^8.4.1",
"express-jwt-v6": "npm:express-jwt@^6.1.2",
"express-jwt-v7": "npm:express-jwt@^7.5.0",
"jose2": "npm:jose@^2.0.6",
"jsonwebtoken": "^9.0.2",
"koa": "^2.14.2",
"koa-jwt": "^4.0.4",
"mocha": "^10.2.0",
"nock": "^13.3.7",
"nyc": "^15.1.0",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"rimraf": "^5.0.5",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
},
"scripts": {
"clean:ts": "rimraf ts-output/",
"lint": "eslint ./src ./tests",
"test:ts": "npm run clean:ts && tsc && NODE_ENV=test mocha --exit --timeout 5000 $(find ./ts-output -name *.tests.js)",
"test:js": "NODE_ENV=test mocha --exit --timeout 5000 $(find ./tests -name *.tests.js)",
"test": "npm run test:js && npm run test:ts",
"test:ci": "nyc --reporter=lcov npm test",
"test-watch": "NODE_ENV=test mocha --exit --timeout 5000 $(find ./tests -name *.tests.js) --watch",
"release": "git tag $npm_package_version && git push && git push --tags && npm publish"
},
"repository": {
"type": "git",
"url": "git+https://github.com/auth0/node-jwks-rsa.git"
},
"keywords": [
"jwks",
"rsa",
"jwt"
],
"author": "Auth0",
"license": "MIT",
"bugs": {
"url": "https://github.com/auth0/node-jwks-rsa/issues"
},
"homepage": "https://github.com/auth0/node-jwks-rsa#readme"
}

91
node_modules/jwks-rsa/src/JwksClient.js generated vendored Normal file
View File

@@ -0,0 +1,91 @@
const logger = require('debug')('jwks');
const { retrieveSigningKeys } = require('./utils') ;
const { request, cacheSigningKey, rateLimitSigningKey, getKeysInterceptor, callbackSupport } = require('./wrappers');
const JwksError = require('./errors/JwksError');
const SigningKeyNotFoundError = require('./errors/SigningKeyNotFoundError');
class JwksClient {
constructor(options) {
this.options = {
rateLimit: false,
cache: true,
timeout: 30000,
...options
};
// Initialize wrappers.
if (this.options.getKeysInterceptor) {
this.getSigningKey = getKeysInterceptor(this, options);
}
if (this.options.rateLimit) {
this.getSigningKey = rateLimitSigningKey(this, options);
}
if (this.options.cache) {
this.getSigningKey = cacheSigningKey(this, options);
}
this.getSigningKey = callbackSupport(this, options);
}
async getKeys() {
logger(`Fetching keys from '${this.options.jwksUri}'`);
try {
const res = await request({
uri: this.options.jwksUri,
headers: this.options.requestHeaders,
agent: this.options.requestAgent,
timeout: this.options.timeout,
fetcher: this.options.fetcher
});
logger('Keys:', res.keys);
return res.keys;
} catch (err) {
const { errorMsg } = err;
logger('Failure:', errorMsg || err);
throw (errorMsg ? new JwksError(errorMsg) : err);
}
}
async getSigningKeys() {
const keys = await this.getKeys();
if (!keys || !keys.length) {
throw new JwksError('The JWKS endpoint did not contain any keys');
}
const signingKeys = await retrieveSigningKeys(keys);
if (!signingKeys.length) {
throw new JwksError('The JWKS endpoint did not contain any signing keys');
}
logger('Signing Keys:', signingKeys);
return signingKeys;
}
async getSigningKey (kid) {
logger(`Fetching signing key for '${kid}'`);
const keys = await this.getSigningKeys();
const kidDefined = kid !== undefined && kid !== null;
if (!kidDefined && keys.length > 1) {
logger('No KID specified and JWKS endpoint returned more than 1 key');
throw new SigningKeyNotFoundError('No KID specified and JWKS endpoint returned more than 1 key');
}
const key = keys.find(k => !kidDefined || k.kid === kid);
if (key) {
return key;
} else {
logger(`Unable to find a signing key that matches '${kid}'`);
throw new SigningKeyNotFoundError(`Unable to find a signing key that matches '${kid}'`);
}
}
}
module.exports = {
JwksClient
};

10
node_modules/jwks-rsa/src/errors/ArgumentError.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
function ArgumentError(message) {
Error.call(this, message);
Error.captureStackTrace(this, this.constructor);
this.name = 'ArgumentError';
this.message = message;
}
ArgumentError.prototype = Object.create(Error.prototype);
ArgumentError.prototype.constructor = ArgumentError;
module.exports = ArgumentError;

10
node_modules/jwks-rsa/src/errors/JwksError.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
function JwksError(message) {
Error.call(this, message);
Error.captureStackTrace(this, this.constructor);
this.name = 'JwksError';
this.message = message;
}
JwksError.prototype = Object.create(Error.prototype);
JwksError.prototype.constructor = JwksError;
module.exports = JwksError;

10
node_modules/jwks-rsa/src/errors/JwksRateLimitError.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
function JwksRateLimitError(message) {
Error.call(this, message);
Error.captureStackTrace(this, this.constructor);
this.name = 'JwksRateLimitError';
this.message = message;
}
JwksRateLimitError.prototype = Object.create(Error.prototype);
JwksRateLimitError.prototype.constructor = JwksRateLimitError;
module.exports = JwksRateLimitError;

View File

@@ -0,0 +1,10 @@
function SigningKeyNotFoundError(message) {
Error.call(this, message);
Error.captureStackTrace(this, this.constructor);
this.name = 'SigningKeyNotFoundError';
this.message = message;
}
SigningKeyNotFoundError.prototype = Object.create(Error.prototype);
SigningKeyNotFoundError.prototype.constructor = SigningKeyNotFoundError;
module.exports = SigningKeyNotFoundError;

6
node_modules/jwks-rsa/src/errors/index.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
ArgumentError: require('./ArgumentError'),
JwksError: require('./JwksError'),
JwksRateLimitError: require('./JwksRateLimitError'),
SigningKeyNotFoundError: require('./SigningKeyNotFoundError')
};

22
node_modules/jwks-rsa/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
const { JwksClient } = require('./JwksClient');
const errors = require('./errors');
const { hapiJwt2Key, hapiJwt2KeyAsync } = require('./integrations/hapi');
const { expressJwtSecret } = require('./integrations/express');
const { koaJwtSecret } = require('./integrations/koa');
const { passportJwtSecret } = require('./integrations/passport');
module.exports = (options) => {
return new JwksClient(options);
};
module.exports.JwksClient = JwksClient;
module.exports.ArgumentError = errors.ArgumentError;
module.exports.JwksError = errors.JwksError;
module.exports.JwksRateLimitError = errors.JwksRateLimitError;
module.exports.SigningKeyNotFoundError = errors.SigningKeyNotFoundError;
module.exports.expressJwtSecret = expressJwtSecret;
module.exports.hapiJwt2Key = hapiJwt2Key;
module.exports.hapiJwt2KeyAsync = hapiJwt2KeyAsync;
module.exports.koaJwtSecret = koaJwtSecret;
module.exports.passportJwtSecret = passportJwtSecret;

15
node_modules/jwks-rsa/src/integrations/config.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
const allowedSignatureAlg = [
'RS256',
'RS384',
'RS512',
'PS256',
'PS384',
'PS512',
'ES256',
'ES256K',
'ES384',
'ES512',
'EdDSA'
];
module.exports = allowedSignatureAlg;

60
node_modules/jwks-rsa/src/integrations/express.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
const { ArgumentError } = require('../errors');
const { JwksClient } = require('../JwksClient');
const supportedAlg = require('./config');
const handleSigningKeyError = (err, cb) => {
// If we didn't find a match, can't provide a key.
if (err && err.name === 'SigningKeyNotFoundError') {
return cb(null);
}
// If an error occured like rate limiting or HTTP issue, we'll bubble up the error.
if (err) {
return cb(err);
}
};
module.exports.expressJwtSecret = function (options) {
if (options === null || options === undefined) {
throw new ArgumentError('An options object must be provided when initializing expressJwtSecret');
}
const client = new JwksClient(options);
const onError = options.handleSigningKeyError || handleSigningKeyError;
const expressJwt7Provider = async (req, token) => {
if (!token) { return; }
const header = token.header;
if (!header || !supportedAlg.includes(header.alg)) {
return;
}
try {
const key = await client.getSigningKey(header.kid);
return key.publicKey || key.rsaPublicKey;
} catch (err) {
return new Promise((resolve, reject) => {
onError(err, (newError) => {
if (!newError) { return resolve(); }
reject(newError);
});
});
}
};
return function secretProvider(req, header, payload, cb) {
//This function has 4 parameters to make it work with express-jwt@6
//but it also supports express-jwt@7 which only has 2.
if (arguments.length === 4) {
expressJwt7Provider(req, { header })
.then(key => {
setImmediate(cb, null, key);
}).catch(err => {
setImmediate(cb, err);
});
return;
}
return expressJwt7Provider(req, arguments[1]);
};
};

59
node_modules/jwks-rsa/src/integrations/hapi.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
const { ArgumentError } = require('../errors');
const { JwksClient } = require('../JwksClient');
const supportedAlg = require('./config');
const handleSigningKeyError = (err, cb) => {
// If we didn't find a match, can't provide a key.
if (err && err.name === 'SigningKeyNotFoundError') {
return cb(err, null, null);
}
// If an error occured like rate limiting or HTTP issue, we'll bubble up the error.
if (err) {
return cb(err, null, null);
}
};
/**
* Call hapiJwt2Key as a Promise
* @param {object} options
* @returns {Promise}
*/
module.exports.hapiJwt2KeyAsync = (options) => {
const secretProvider = module.exports.hapiJwt2Key(options);
return function(decoded) {
return new Promise((resolve, reject) => {
const cb = (err, key) => {
(!key || err) ? reject(err) : resolve({ key });
};
secretProvider(decoded, cb);
});
};
};
module.exports.hapiJwt2Key = function (options) {
if (options === null || options === undefined) {
throw new ArgumentError('An options object must be provided when initializing hapiJwt2Key');
}
const client = new JwksClient(options);
const onError = options.handleSigningKeyError || handleSigningKeyError;
return function secretProvider(decoded, cb) {
// We cannot find a signing certificate if there is no header (no kid).
if (!decoded || !decoded.header) {
return cb(new Error('Cannot find a signing certificate if there is no header'), null, null);
}
if (!supportedAlg.includes(decoded.header.alg)) {
return cb(new Error('Unsupported algorithm ' + decoded.header.alg + ' supplied.'), null, null);
}
client.getSigningKey(decoded.header.kid)
.then(key => {
return cb(null, key.publicKey || key.rsaPublicKey, key);
}).catch(err => {
return onError(err, (newError) => cb(newError, null, null));
});
};
};

30
node_modules/jwks-rsa/src/integrations/koa.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
const { ArgumentError } = require('../errors');
const { JwksClient } = require('../JwksClient');
const supportedAlg = require('./config');
module.exports.koaJwtSecret = function (options = {}) {
if (!options.jwksUri) {
throw new ArgumentError('No JWKS provided. Please provide a jwksUri');
}
const client = new JwksClient(options);
return function secretProvider({ alg, kid } = {}) {
return new Promise((resolve, reject) => {
if (!supportedAlg.includes(alg)) {
return reject(new Error('Missing / invalid token algorithm'));
}
client.getSigningKey(kid)
.then(key => {
resolve(key.publicKey || key.rsaPublicKey);
}).catch(err => {
if (options.handleSigningKeyError) {
return options.handleSigningKeyError(err).then(reject);
}
return reject(err);
});
});
};
};

52
node_modules/jwks-rsa/src/integrations/passport.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
const jose = require('jose');
const { ArgumentError } = require('../errors');
const { JwksClient } = require('../JwksClient');
const supportedAlg = require('./config');
const handleSigningKeyError = (err, cb) => {
// If we didn't find a match, can't provide a key.
if (err && err.name === 'SigningKeyNotFoundError') {
return cb(null);
}
// If an error occured like rate limiting or HTTP issue, we'll bubble up the error.
if (err) {
return cb(err);
}
};
module.exports.passportJwtSecret = function (options) {
if (options === null || options === undefined) {
throw new ArgumentError('An options object must be provided when initializing passportJwtSecret');
}
if (!options.jwksUri) {
throw new ArgumentError('No JWKS provided. Please provide a jwksUri');
}
const client = new JwksClient(options);
const onError = options.handleSigningKeyError || handleSigningKeyError;
return function secretProvider(req, rawJwtToken, cb) {
let decoded;
try {
decoded = {
payload: jose.decodeJwt(rawJwtToken),
header: jose.decodeProtectedHeader(rawJwtToken)
};
} catch (err) {
decoded = null;
}
if (!decoded || !supportedAlg.includes(decoded.header.alg)) {
return cb(null, null);
}
client.getSigningKey(decoded.header.kid)
.then(key => {
cb(null, key.publicKey || key.rsaPublicKey);
}).catch(err => {
onError(err, (newError) => cb(newError, null));
});
};
};

80
node_modules/jwks-rsa/src/utils.js generated vendored Normal file
View File

@@ -0,0 +1,80 @@
const jose = require('jose');
const JwksError = require('./errors/JwksError');
function resolveAlg(jwk) {
if (jwk.alg) {
return jwk.alg;
}
if (jwk.kty === 'RSA') {
return 'RS256';
}
if (jwk.kty === 'EC') {
switch (jwk.crv) {
case 'P-256':
return 'ES256';
case 'secp256k1':
return 'ES256K';
case 'P-384':
return 'ES384';
case 'P-521':
return 'ES512';
}
}
if (jwk.kty === 'OKP') {
switch (jwk.crv) {
case 'Ed25519':
case 'Ed448':
return 'EdDSA';
}
}
throw new JwksError('Unsupported JWK');
}
async function retrieveSigningKeys(jwks) {
const results = [];
jwks = jwks
.filter(({ use }) => use === 'sig' || use === undefined)
.filter(({ kty }) => kty === 'RSA' || kty === 'EC' || kty === 'OKP');
for (const jwk of jwks) {
try {
const key = await jose.importJWK({ ...jwk, ext: true }, resolveAlg(jwk));
if (key.type !== 'public') {
continue;
}
let getSpki;
switch (key[Symbol.toStringTag]) {
case 'CryptoKey': {
const spki = await jose.exportSPKI(key);
getSpki = () => spki;
break;
}
case 'KeyObject':
// Assume legacy Node.js version without the Symbol.toStringTag backported
// Fall through
default:
getSpki = () => key.export({ format: 'pem', type: 'spki' });
}
results.push({
get publicKey() { return getSpki(); },
get rsaPublicKey() { return getSpki(); },
getPublicKey() { return getSpki(); },
...(typeof jwk.kid === 'string' && jwk.kid ? { kid: jwk.kid } : undefined),
...(typeof jwk.alg === 'string' && jwk.alg ? { alg: jwk.alg } : undefined)
});
} catch (err) {
continue;
}
}
return results;
}
module.exports = {
retrieveSigningKeys
};

15
node_modules/jwks-rsa/src/wrappers/cache.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
const logger = require('debug')('jwks');
const memoizer = require('lru-memoizer');
const { promisify, callbackify } = require('util');
function cacheWrapper(client, { cacheMaxEntries = 5, cacheMaxAge = 600000 }) {
logger(`Configured caching of signing keys. Max: ${cacheMaxEntries} / Age: ${cacheMaxAge}`);
return promisify(memoizer({
hash: (kid) => kid,
load: callbackify(client.getSigningKey.bind(client)),
maxAge: cacheMaxAge,
max: cacheMaxEntries
}));
}
module.exports.default = cacheWrapper;

16
node_modules/jwks-rsa/src/wrappers/callbackSupport.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
const { callbackify } = require('util');
const callbackSupport = (client) => {
const getSigningKey = client.getSigningKey.bind(client);
return (kid, cb) => {
if (cb) {
const callbackFunc = callbackify(getSigningKey);
return callbackFunc(kid, cb);
}
return getSigningKey(kid);
};
};
module.exports.default = callbackSupport;

7
node_modules/jwks-rsa/src/wrappers/index.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
module.exports = {
request: require('./request').default,
cacheSigningKey: require('./cache').default,
rateLimitSigningKey: require('./rateLimit').default,
getKeysInterceptor: require('./interceptor').default,
callbackSupport: require('./callbackSupport').default
};

30
node_modules/jwks-rsa/src/wrappers/interceptor.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
const retrieveSigningKeys = require('../utils').retrieveSigningKeys;
/**
* Uses getKeysInterceptor to allow users to retrieve keys from a file,
* external cache, or provided object before falling back to the jwksUri endpoint
*/
function getKeysInterceptor(client, { getKeysInterceptor }) {
const getSigningKey = client.getSigningKey.bind(client);
return async (kid) => {
const keys = await getKeysInterceptor();
let signingKeys;
if (keys && keys.length) {
signingKeys = await retrieveSigningKeys(keys);
}
if (signingKeys && signingKeys.length) {
const key = signingKeys.find(k => !kid || k.kid === kid);
if (key) {
return key;
}
}
return getSigningKey(kid);
};
}
module.exports.default = getKeysInterceptor;

34
node_modules/jwks-rsa/src/wrappers/rateLimit.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
const logger = require('debug')('jwks');
const { RateLimiter } = require('limiter');
const JwksRateLimitError = require('../errors/JwksRateLimitError');
function rateLimitWrapper(client, { jwksRequestsPerMinute = 10 }) {
const getSigningKey = client.getSigningKey.bind(client);
const limiter = new RateLimiter(jwksRequestsPerMinute, 'minute', true);
logger(`Configured rate limiting to JWKS endpoint at ${jwksRequestsPerMinute}/minute`);
return async (kid) => await new Promise((resolve, reject) => {
limiter.removeTokens(1, async (err, remaining) => {
if (err) {
reject(err);
}
logger('Requests to the JWKS endpoint available for the next minute:', remaining);
if (remaining < 0) {
logger('Too many requests to the JWKS endpoint');
reject(new JwksRateLimitError('Too many requests to the JWKS endpoint'));
} else {
try {
const key = await getSigningKey(kid);
resolve(key);
} catch (error) {
reject(error);
}
}
});
});
}
module.exports.default = rateLimitWrapper;

52
node_modules/jwks-rsa/src/wrappers/request.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
const http = require('http');
const https = require('https');
const urlUtil = require('url');
module.exports.default = (options) => {
if (options.fetcher) {
return options.fetcher(options.uri);
}
return new Promise((resolve, reject) => {
const {
hostname,
path,
port,
protocol
} = urlUtil.parse(options.uri);
const requestOptions = {
hostname,
path,
port,
method: 'GET',
...(options.headers && { headers: { ...options.headers } }),
...(options.timeout && { timeout: options.timeout }),
...(options.agent && { agent: options.agent })
};
const httpRequestLib = protocol === 'https:' ? https : http;
const httpRequest = httpRequestLib.request(requestOptions, (res) => {
let rawData = '';
res.setEncoding('utf8');
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
if (res.statusCode < 200 || res.statusCode >= 300) {
const errorMsg = res.body && (res.body.message || res.body) || res.statusMessage || `Http Error ${res.statusCode}`;
reject({ errorMsg });
} else {
try {
resolve(rawData && JSON.parse(rawData));
} catch (error) {
reject(error);
}
}
});
});
httpRequest
.on('timeout', () => httpRequest.destroy())
.on('error', (e) => reject(e))
.end();
});
};