Update app and tooling
This commit is contained in:
parent
3046531bdd
commit
e620ec7349
4950 changed files with 2975120 additions and 10 deletions
125
node_modules/jose/dist/node/cjs/jwks/local.js
generated
vendored
Normal file
125
node_modules/jose/dist/node/cjs/jwks/local.js
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createLocalJWKSet = createLocalJWKSet;
|
||||
const import_js_1 = require("../key/import.js");
|
||||
const errors_js_1 = require("../util/errors.js");
|
||||
const is_object_js_1 = require("../lib/is_object.js");
|
||||
function getKtyFromAlg(alg) {
|
||||
switch (typeof alg === 'string' && alg.slice(0, 2)) {
|
||||
case 'RS':
|
||||
case 'PS':
|
||||
return 'RSA';
|
||||
case 'ES':
|
||||
return 'EC';
|
||||
case 'Ed':
|
||||
return 'OKP';
|
||||
default:
|
||||
throw new errors_js_1.JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
|
||||
}
|
||||
}
|
||||
function isJWKSLike(jwks) {
|
||||
return (jwks &&
|
||||
typeof jwks === 'object' &&
|
||||
Array.isArray(jwks.keys) &&
|
||||
jwks.keys.every(isJWKLike));
|
||||
}
|
||||
function isJWKLike(key) {
|
||||
return (0, is_object_js_1.default)(key);
|
||||
}
|
||||
function clone(obj) {
|
||||
if (typeof structuredClone === 'function') {
|
||||
return structuredClone(obj);
|
||||
}
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
class LocalJWKSet {
|
||||
_jwks;
|
||||
_cached = new WeakMap();
|
||||
constructor(jwks) {
|
||||
if (!isJWKSLike(jwks)) {
|
||||
throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed');
|
||||
}
|
||||
this._jwks = clone(jwks);
|
||||
}
|
||||
async getKey(protectedHeader, token) {
|
||||
const { alg, kid } = { ...protectedHeader, ...token?.header };
|
||||
const kty = getKtyFromAlg(alg);
|
||||
const candidates = this._jwks.keys.filter((jwk) => {
|
||||
let candidate = kty === jwk.kty;
|
||||
if (candidate && typeof kid === 'string') {
|
||||
candidate = kid === jwk.kid;
|
||||
}
|
||||
if (candidate && typeof jwk.alg === 'string') {
|
||||
candidate = alg === jwk.alg;
|
||||
}
|
||||
if (candidate && typeof jwk.use === 'string') {
|
||||
candidate = jwk.use === 'sig';
|
||||
}
|
||||
if (candidate && Array.isArray(jwk.key_ops)) {
|
||||
candidate = jwk.key_ops.includes('verify');
|
||||
}
|
||||
if (candidate && alg === 'EdDSA') {
|
||||
candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';
|
||||
}
|
||||
if (candidate) {
|
||||
switch (alg) {
|
||||
case 'ES256':
|
||||
candidate = jwk.crv === 'P-256';
|
||||
break;
|
||||
case 'ES256K':
|
||||
candidate = jwk.crv === 'secp256k1';
|
||||
break;
|
||||
case 'ES384':
|
||||
candidate = jwk.crv === 'P-384';
|
||||
break;
|
||||
case 'ES512':
|
||||
candidate = jwk.crv === 'P-521';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
});
|
||||
const { 0: jwk, length } = candidates;
|
||||
if (length === 0) {
|
||||
throw new errors_js_1.JWKSNoMatchingKey();
|
||||
}
|
||||
if (length !== 1) {
|
||||
const error = new errors_js_1.JWKSMultipleMatchingKeys();
|
||||
const { _cached } = this;
|
||||
error[Symbol.asyncIterator] = async function* () {
|
||||
for (const jwk of candidates) {
|
||||
try {
|
||||
yield await importWithAlgCache(_cached, jwk, alg);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
return importWithAlgCache(this._cached, jwk, alg);
|
||||
}
|
||||
}
|
||||
async function importWithAlgCache(cache, jwk, alg) {
|
||||
const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);
|
||||
if (cached[alg] === undefined) {
|
||||
const key = await (0, import_js_1.importJWK)({ ...jwk, ext: true }, alg);
|
||||
if (key instanceof Uint8Array || key.type !== 'public') {
|
||||
throw new errors_js_1.JWKSInvalid('JSON Web Key Set members must be public keys');
|
||||
}
|
||||
cached[alg] = key;
|
||||
}
|
||||
return cached[alg];
|
||||
}
|
||||
function createLocalJWKSet(jwks) {
|
||||
const set = new LocalJWKSet(jwks);
|
||||
const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
|
||||
Object.defineProperties(localJWKSet, {
|
||||
jwks: {
|
||||
value: () => clone(set._jwks),
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
},
|
||||
});
|
||||
return localJWKSet;
|
||||
}
|
||||
152
node_modules/jose/dist/node/cjs/jwks/remote.js
generated
vendored
Normal file
152
node_modules/jose/dist/node/cjs/jwks/remote.js
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.experimental_jwksCache = exports.jwksCache = void 0;
|
||||
exports.createRemoteJWKSet = createRemoteJWKSet;
|
||||
const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js");
|
||||
const errors_js_1 = require("../util/errors.js");
|
||||
const local_js_1 = require("./local.js");
|
||||
const is_object_js_1 = require("../lib/is_object.js");
|
||||
function isCloudflareWorkers() {
|
||||
return (typeof WebSocketPair !== 'undefined' ||
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||
|
||||
(typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel'));
|
||||
}
|
||||
let USER_AGENT;
|
||||
if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
|
||||
const NAME = 'jose';
|
||||
const VERSION = 'v5.9.6';
|
||||
USER_AGENT = `${NAME}/${VERSION}`;
|
||||
}
|
||||
exports.jwksCache = Symbol();
|
||||
function isFreshJwksCache(input, cacheMaxAge) {
|
||||
if (typeof input !== 'object' || input === null) {
|
||||
return false;
|
||||
}
|
||||
if (!('uat' in input) || typeof input.uat !== 'number' || Date.now() - input.uat >= cacheMaxAge) {
|
||||
return false;
|
||||
}
|
||||
if (!('jwks' in input) ||
|
||||
!(0, is_object_js_1.default)(input.jwks) ||
|
||||
!Array.isArray(input.jwks.keys) ||
|
||||
!Array.prototype.every.call(input.jwks.keys, is_object_js_1.default)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
class RemoteJWKSet {
|
||||
_url;
|
||||
_timeoutDuration;
|
||||
_cooldownDuration;
|
||||
_cacheMaxAge;
|
||||
_jwksTimestamp;
|
||||
_pendingFetch;
|
||||
_options;
|
||||
_local;
|
||||
_cache;
|
||||
constructor(url, options) {
|
||||
if (!(url instanceof URL)) {
|
||||
throw new TypeError('url must be an instance of URL');
|
||||
}
|
||||
this._url = new URL(url.href);
|
||||
this._options = { agent: options?.agent, headers: options?.headers };
|
||||
this._timeoutDuration =
|
||||
typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000;
|
||||
this._cooldownDuration =
|
||||
typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000;
|
||||
this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000;
|
||||
if (options?.[exports.jwksCache] !== undefined) {
|
||||
this._cache = options?.[exports.jwksCache];
|
||||
if (isFreshJwksCache(options?.[exports.jwksCache], this._cacheMaxAge)) {
|
||||
this._jwksTimestamp = this._cache.uat;
|
||||
this._local = (0, local_js_1.createLocalJWKSet)(this._cache.jwks);
|
||||
}
|
||||
}
|
||||
}
|
||||
coolingDown() {
|
||||
return typeof this._jwksTimestamp === 'number'
|
||||
? Date.now() < this._jwksTimestamp + this._cooldownDuration
|
||||
: false;
|
||||
}
|
||||
fresh() {
|
||||
return typeof this._jwksTimestamp === 'number'
|
||||
? Date.now() < this._jwksTimestamp + this._cacheMaxAge
|
||||
: false;
|
||||
}
|
||||
async getKey(protectedHeader, token) {
|
||||
if (!this._local || !this.fresh()) {
|
||||
await this.reload();
|
||||
}
|
||||
try {
|
||||
return await this._local(protectedHeader, token);
|
||||
}
|
||||
catch (err) {
|
||||
if (err instanceof errors_js_1.JWKSNoMatchingKey) {
|
||||
if (this.coolingDown() === false) {
|
||||
await this.reload();
|
||||
return this._local(protectedHeader, token);
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async reload() {
|
||||
if (this._pendingFetch && isCloudflareWorkers()) {
|
||||
this._pendingFetch = undefined;
|
||||
}
|
||||
const headers = new Headers(this._options.headers);
|
||||
if (USER_AGENT && !headers.has('User-Agent')) {
|
||||
headers.set('User-Agent', USER_AGENT);
|
||||
this._options.headers = Object.fromEntries(headers.entries());
|
||||
}
|
||||
this._pendingFetch ||= (0, fetch_jwks_js_1.default)(this._url, this._timeoutDuration, this._options)
|
||||
.then((json) => {
|
||||
this._local = (0, local_js_1.createLocalJWKSet)(json);
|
||||
if (this._cache) {
|
||||
this._cache.uat = Date.now();
|
||||
this._cache.jwks = json;
|
||||
}
|
||||
this._jwksTimestamp = Date.now();
|
||||
this._pendingFetch = undefined;
|
||||
})
|
||||
.catch((err) => {
|
||||
this._pendingFetch = undefined;
|
||||
throw err;
|
||||
});
|
||||
await this._pendingFetch;
|
||||
}
|
||||
}
|
||||
function createRemoteJWKSet(url, options) {
|
||||
const set = new RemoteJWKSet(url, options);
|
||||
const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
|
||||
Object.defineProperties(remoteJWKSet, {
|
||||
coolingDown: {
|
||||
get: () => set.coolingDown(),
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
},
|
||||
fresh: {
|
||||
get: () => set.fresh(),
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
},
|
||||
reload: {
|
||||
value: () => set.reload(),
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
},
|
||||
reloading: {
|
||||
get: () => !!set._pendingFetch,
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
},
|
||||
jwks: {
|
||||
value: () => set._local?.jwks(),
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
},
|
||||
});
|
||||
return remoteJWKSet;
|
||||
}
|
||||
exports.experimental_jwksCache = exports.jwksCache;
|
||||
Loading…
Add table
Add a link
Reference in a new issue