@sourceregistry/node-jwt 1.5.11 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +753 -22
- package/dist/index.js.map +1 -1
- package/dist/jwt/index.d.ts +5 -3
- package/dist/jwt/promises.d.ts +28 -28
- package/dist/promises.cjs +2 -2
- package/dist/promises.cjs.map +1 -1
- package/dist/promises.js +30 -43
- package/dist/promises.js.map +1 -1
- package/package.json +10 -10
- package/dist/index-BJnjMyHr.js +0 -803
- package/dist/index-BJnjMyHr.js.map +0 -1
- package/dist/index-BzmHAEeR.cjs +0 -2
- package/dist/index-BzmHAEeR.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -226,6 +226,7 @@ import { verify } from '@sourceregistry/node-jwt';
|
|
|
226
226
|
|
|
227
227
|
const result = verify(token, publicKeyOrSecret, {
|
|
228
228
|
algorithms: ['RS256'], // pin expected algorithm(s)
|
|
229
|
+
tokenTypes: ['JWT'], // allowlist protected-header typ values
|
|
229
230
|
issuer: 'https://issuer.example',
|
|
230
231
|
audience: 'my-service',
|
|
231
232
|
clockSkew: 30, // seconds
|
|
@@ -236,6 +237,8 @@ const result = verify(token, publicKeyOrSecret, {
|
|
|
236
237
|
Recommended operational checks:
|
|
237
238
|
|
|
238
239
|
* Pin `algorithms` in every verify call (the list must be non-empty).
|
|
240
|
+
* Keep `tokenTypes` narrowly scoped when accepting specialized JWT profiles. It defaults to
|
|
241
|
+
`['JWT']`; a missing `typ` header remains valid as permitted by RFC 7519.
|
|
239
242
|
* Always validate `issuer` and `audience` for external tokens.
|
|
240
243
|
* Use short token lifetimes and enforce `maxTokenAge`; tokens must include `iat` when it is configured.
|
|
241
244
|
* Rotate keys regularly and configure JWKS cache `ttl` for your threat model.
|
|
@@ -297,6 +300,22 @@ This prevents the library from silently accepting JWTs that require header proce
|
|
|
297
300
|
|
|
298
301
|
Includes algorithm whitelist protection and full claim validation.
|
|
299
302
|
|
|
303
|
+
Use `tokenTypes` to accept an explicitly identified JWT profile without disabling type checks:
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
const result = verify(logoutToken, publicKey, {
|
|
307
|
+
algorithms: ['RS256'],
|
|
308
|
+
tokenTypes: ['JWT', 'logout+jwt']
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
For example, OpenID Connect Back-Channel Logout recommends `typ: "logout+jwt"` for Logout Tokens,
|
|
313
|
+
so a relying party can allow that profile without accepting arbitrary JWT types. See the
|
|
314
|
+
[Back-Channel Logout specification](https://openid.net/specs/openid-connect-backchannel-1_0.html#LogoutToken).
|
|
315
|
+
|
|
316
|
+
If a `typ` header is present it must be in the allowlist. The option must be a non-empty array of
|
|
317
|
+
non-empty strings. Omitting it preserves the strict `['JWT']` default.
|
|
318
|
+
|
|
300
319
|
When `maxTokenAge` is configured, the token must include a numeric `iat` claim. `ignoreExpiration`, when used, must be a boolean.
|
|
301
320
|
|
|
302
321
|
**Error Codes include:**
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BzmHAEeR.cjs");exports.AutodetectAlgorithm=e.AutodetectAlgorithm;exports.JWK=e.JWK;exports.JWKS=e.JWKS;exports.JWKSToKeyObject=e.JWKSToKeyObject;exports.JWT=e.JWT;exports.SignatureAlgorithm=e.SignatureAlgorithm;exports.SupportedAlgorithms=e.SupportedAlgorithms;exports.base64Url=e.base64Url;exports.computeX5T=e.computeX5T;exports.decode=e.decode;exports.exportJWK=e.exportJWK;exports.fromWeb=e.fromWeb;exports.getJWKThumbprint=e.getJWKThumbprint;exports.importJWK=e.importJWK;exports.normalizeJWK=e.normalizeJWK;exports.normalizeJWKS=e.normalizeJWKS;exports.sign=e.sign;exports.toPublicJWK=e.toPublicJWK;exports.verify=e.verify;
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("crypto");c=s(c,1);var l={encode:e=>Buffer.from(e).toString(`base64url`),decode:e=>Buffer.from(e,`base64url`).toString()},u=(e,t)=>e.length===t.length&&(0,c.timingSafeEqual)(Buffer.from(e),Buffer.from(t)),d=/^[A-Za-z0-9_-]+$/;function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e){return typeof e==`number`&&Number.isFinite(e)}function m(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function h(e){let t=[{claim:`iss`,valid:e.iss===void 0||typeof e.iss==`string`,expected:`string`},{claim:`sub`,valid:e.sub===void 0||typeof e.sub==`string`,expected:`string`},{claim:`jti`,valid:e.jti===void 0||typeof e.jti==`string`,expected:`string`},{claim:`sid`,valid:e.sid===void 0||typeof e.sid==`string`,expected:`string`},{claim:`iat`,valid:e.iat===void 0||p(e.iat),expected:`number`},{claim:`exp`,valid:e.exp===void 0||p(e.exp),expected:`number`},{claim:`nbf`,valid:e.nbf===void 0||p(e.nbf),expected:`number`}];for(let e of t)if(!e.valid)return{reason:`Invalid "${e.claim}" claim: expected ${e.expected}`,code:`INVALID_CLAIM`};return e.aud!==void 0&&!(typeof e.aud==`string`||m(e.aud))?{reason:`Invalid "aud" claim: expected string or string[]`,code:`INVALID_CLAIM`}:null}function g(e){if(e.signatureFormat!==void 0&&e.signatureFormat!==`der`&&e.signatureFormat!==`jose`)return{reason:`Invalid signatureFormat option: expected "der" or "jose"`,code:`INVALID_OPTIONS`};if(e.clockSkew!==void 0&&(!p(e.clockSkew)||e.clockSkew<0))return{reason:`Invalid clockSkew option: expected a non-negative finite number`,code:`INVALID_OPTIONS`};if(e.maxTokenAge!==void 0&&(!p(e.maxTokenAge)||e.maxTokenAge<0))return{reason:`Invalid maxTokenAge option: expected a non-negative finite number`,code:`INVALID_OPTIONS`};if(e.ignoreExpiration!==void 0&&typeof e.ignoreExpiration!=`boolean`)return{reason:`Invalid ignoreExpiration option: expected boolean`,code:`INVALID_OPTIONS`};if(e.issuer!==void 0&&typeof e.issuer!=`string`)return{reason:`Invalid issuer option: expected string`,code:`INVALID_OPTIONS`};if(e.subject!==void 0&&typeof e.subject!=`string`)return{reason:`Invalid subject option: expected string`,code:`INVALID_OPTIONS`};if(e.jwtId!==void 0&&typeof e.jwtId!=`string`)return{reason:`Invalid jwtId option: expected string`,code:`INVALID_OPTIONS`};if(e.audience!==void 0&&!(typeof e.audience==`string`||m(e.audience)))return{reason:`Invalid audience option: expected string or string[]`,code:`INVALID_OPTIONS`};if(e.algorithms!==void 0){if(!Array.isArray(e.algorithms)||e.algorithms.length===0)return{reason:`Invalid algorithms option: expected a non-empty array`,code:`INVALID_OPTIONS`};let t=e.algorithms.find(e=>!(e in T));if(t)return{reason:`Invalid algorithms option: unsupported algorithm "${t}"`,code:`INVALID_OPTIONS`}}if(e.tokenTypes!==void 0){if(!Array.isArray(e.tokenTypes)||e.tokenTypes.length===0||!m(e.tokenTypes))return{reason:`Invalid tokenTypes option: expected a non-empty string[]`,code:`INVALID_OPTIONS`};if(e.tokenTypes.some(e=>e.length===0))return{reason:`Invalid tokenTypes option: token types must not be empty`,code:`INVALID_OPTIONS`}}return null}function _(e){return e.crit===void 0?null:!m(e.crit)||e.crit.length===0?{reason:`Invalid "crit" header: expected non-empty string[]`,code:`INVALID_HEADER`}:{reason:`Unsupported critical header parameters: ${e.crit.join(`, `)}`,code:`UNSUPPORTED_CRITICAL_HEADER`}}function v(e){switch(e){case`ES256`:case`ES256K`:return 64;case`ES384`:return 96;case`ES512`:return 132;default:throw Error(`Unsupported ECDSA alg for JOSE conversion: ${e}`)}}function y(e,t){let n=0;if(e[n++]!==48)throw Error(`Invalid DER ECDSA signature`);let r=e[n++];if(r&128){let t=r&127;r=0;for(let i=0;i<t;i++)r=r<<8|e[n++]}if(e[n++]!==2)throw Error(`Invalid DER ECDSA signature (r)`);let i=e[n++],a=e.subarray(n,n+i);if(n+=i,e[n++]!==2)throw Error(`Invalid DER ECDSA signature (s)`);let o=e[n++],s=e.subarray(n,n+o);for(;a.length>t/2&&a[0]===0;)a=a.subarray(1);for(;s.length>t/2&&s[0]===0;)s=s.subarray(1);let c=Buffer.concat([Buffer.alloc(t/2-a.length,0),a]),l=Buffer.concat([Buffer.alloc(t/2-s.length,0),s]);return Buffer.concat([c,l])}function b(e){let t=e.length/2,n=e.subarray(0,t),r=e.subarray(t);for(;n.length>1&&n[0]===0&&!(n[1]&128);)n=n.subarray(1);for(;r.length>1&&r[0]===0&&!(r[1]&128);)r=r.subarray(1);n[0]&128&&(n=Buffer.concat([Buffer.from([0]),n])),r[0]&128&&(r=Buffer.concat([Buffer.from([0]),r]));let i=Buffer.concat([Buffer.from([2,n.length]),n]),a=Buffer.concat([Buffer.from([2,r.length]),r]),o=i.length+a.length,s;if(o<128)s=Buffer.from([o]);else{let e=[],t=o;for(;t>0;)e.unshift(t&255),t>>=8;s=Buffer.from([128|e.length,...e])}return Buffer.concat([Buffer.from([48]),s,i,a])}function x(e){return e===`ES256`||e===`ES384`||e===`ES512`||e===`ES256K`}var S=e=>({sign:(t,n)=>(0,c.createHmac)(e,n).update(t).digest(`base64url`),verify:(t,n,r)=>u((0,c.createHmac)(e,n).update(t).digest(`base64url`),r)}),C=e=>({sign:(t,n)=>(0,c.createSign)(e).update(t).end().sign(n).toString(`base64url`),verify:(t,n,r)=>{try{return(0,c.createVerify)(e).update(t).end().verify(n,Buffer.from(r,`base64url`))}catch{return!1}}}),w=(e,t)=>({sign:(n,r)=>(0,c.createSign)(e).update(n).end().sign({key:r,padding:c.default.constants.RSA_PKCS1_PSS_PADDING,saltLength:t}).toString(`base64url`),verify:(n,r,i)=>{try{return(0,c.createVerify)(e).update(n).end().verify({key:r,padding:c.default.constants.RSA_PKCS1_PSS_PADDING,saltLength:t},Buffer.from(i,`base64url`))}catch{return!1}}}),T={HS256:S(`sha256`),HS384:S(`sha384`),HS512:S(`sha512`),RS256:C(`RSA-SHA256`),RS384:C(`RSA-SHA384`),RS512:C(`RSA-SHA512`),ES256:C(`SHA256`),ES384:C(`SHA384`),ES512:C(`SHA512`),ES256K:C(`SHA256`),PS256:w(`RSA-SHA256`,32),PS384:w(`RSA-SHA384`,48),PS512:w(`RSA-SHA512`,64),EdDSA:{sign:(e,t)=>(0,c.sign)(null,typeof e==`string`?Buffer.from(e,`utf8`):e,t).toString(`base64url`),verify:(e,t,n)=>{try{return(0,c.verify)(null,typeof e==`string`?Buffer.from(e,`utf8`):e,t,Buffer.from(n,`base64url`))}catch{return!1}}}},E=Object.keys(T);function D(e){if(e.type===`secret`)return`HS256`;if(e.type!==`private`)throw Error(`Only private or symmetric keys can be used to sign JWTs`);let t=e.asymmetricKeyType,n=e.asymmetricKeyDetails;switch(t){case`rsa`:return`RS256`;case`rsa-pss`:{let e=(n==null?void 0:n.hashAlgorithm)??`sha256`;switch(e){case`sha256`:return`PS256`;case`sha384`:return`PS384`;case`sha512`:return`PS512`;default:throw Error(`Unsupported RSA-PSS hash algorithm: ${e}`)}}case`ec`:{let e=n==null?void 0:n.namedCurve;switch(e){case`P-256`:case`prime256v1`:return`ES256`;case`P-384`:case`secp384r1`:return`ES384`;case`P-521`:case`secp521r1`:return`ES512`;case`secp256k1`:return`ES256K`;default:throw Error(`Unsupported EC curve: ${e}`)}}case`ed25519`:return`EdDSA`;default:throw Error(`Unsupported asymmetric key type: ${t}`)}}function O(e,t){if(typeof e==`object`&&`type`in e)return e;try{return t===`sign`?(0,c.createPrivateKey)(e):(0,c.createPublicKey)(e)}catch{if(t===`sign`){try{(0,c.createPublicKey)(e)}catch{if(typeof e==`string`)return(0,c.createSecretKey)(Buffer.from(e,`utf8`));if(Buffer.isBuffer(e))return(0,c.createSecretKey)(e);throw Error(`Unsupported key type`)}throw Error(`A public key cannot be used to sign JWTs`)}if(typeof e==`string`)return(0,c.createSecretKey)(Buffer.from(e,`utf8`));if(Buffer.isBuffer(e))return(0,c.createSecretKey)(e);throw Error(`Unsupported key type`)}}function k(e,t,n){if(t.startsWith(`HS`)){if(e.type!==`secret`)throw Error(`${t} requires a symmetric secret key`);return}if(n===`sign`&&e.type!==`private`)throw Error(`${t} requires a private key for signing`);if(n===`verify`&&e.type!==`public`&&e.type!==`private`)throw Error(`${t} requires a public or private key for verification`);let r=e.asymmetricKeyType;if(t.startsWith(`RS`)&&r!==`rsa`)throw Error(`${t} requires an RSA key`);if(t.startsWith(`PS`)&&r!==`rsa`&&r!==`rsa-pss`)throw Error(`${t} requires an RSA or RSA-PSS key`);if(t===`EdDSA`&&r!==`ed25519`)throw Error(`EdDSA requires an Ed25519 key`);if(x(t)){var i;let n=(i=e.asymmetricKeyDetails)==null?void 0:i.namedCurve,a=[];switch(t){case`ES256`:a=[`P-256`,`prime256v1`];break;case`ES384`:a=[`P-384`,`secp384r1`];break;case`ES512`:a=[`P-521`,`secp521r1`];break;case`ES256K`:a=[`secp256k1`]}if(r!==`ec`||!a.includes(n??``))throw Error(`${t} requires its matching EC curve`)}}var A=e=>{let t=e.split(`.`);if(t.length!==3)throw Error(`Invalid JWT: must contain exactly 3 parts separated by "."`);let[n,r,i]=t;if(!n||!r||!i)throw Error(`Invalid JWT: empty part detected`);if(!d.test(n)||!d.test(r)||!d.test(i))throw Error(`Invalid JWT: non-base64url characters detected`);try{let e=JSON.parse(l.decode(n)),t=JSON.parse(l.decode(r));if(!f(e)||!f(t))throw Error(`header and payload must be JSON objects`);let a=e,o=t;if(typeof a.alg!=`string`||a.alg.length===0)throw Error(`header.alg must be a non-empty string`);if(a.typ!==void 0&&typeof a.typ!=`string`)throw Error(`header.typ must be a string`);if(a.kid!==void 0&&typeof a.kid!=`string`)throw Error(`header.kid must be a string`);if(a.crit!==void 0&&(!m(a.crit)||a.crit.length===0))throw Error(`header.crit must be a non-empty string[]`);return{header:a,payload:o,signature:i}}catch(e){throw Error(`Invalid JWT: malformed header or payload (${e.message})`)}},j=(e,t,n={})=>{let r=O(t,`sign`),i=n.alg??D(r),a=n.signatureFormat??(x(i)?`jose`:`der`),o=n.typ??`JWT`;if(!(i in T))throw Error(`Unsupported algorithm: ${i}`);k(r,i,`sign`);let s={alg:i,typ:o};n.kid&&(s.kid=n.kid);let c=l.encode(JSON.stringify(s)),u=l.encode(JSON.stringify(e)),d=`${c}.${u}`,f=T[i].sign(d,r);return a===`jose`&&x(i)&&(f=y(Buffer.from(f,`base64url`),v(i)).toString(`base64url`)),`${c}.${u}.${f}`},M=(e,t,n={})=>{let r=g(n);if(r)return{valid:!1,error:r};let i;try{i=A(e)}catch(e){return{valid:!1,error:{reason:e.message,code:`INVALID_TOKEN`}}}let{header:a,payload:o,signature:s}=i,c=_(a);if(c)return{valid:!1,error:c};let l=h(o);if(l)return{valid:!1,error:l};let u=a.alg;if(!(u in T))return{valid:!1,error:{reason:`Unsupported or unknown algorithm: ${a.alg}`,code:`INVALID_ALGORITHM`}};if(n.algorithms&&n.algorithms.length>0&&!n.algorithms.includes(u))return{valid:!1,error:{reason:`Algorithm "${u}" is not in the allowed algorithms list`,code:`ALGORITHM_NOT_ALLOWED`}};let d=n.tokenTypes??[`JWT`];if(a.typ!==void 0&&!d.includes(a.typ))return{valid:!1,error:{reason:`Invalid token type: expected one of ${d.map(e=>`'${e}'`).join(`, `)}, got '${a.typ}'`,code:`INVALID_TYPE`}};let[f,p]=e.split(`.`),m=`${f}.${p}`,y;try{y=O(t,`verify`),k(y,u,`verify`)}catch(e){return{valid:!1,error:{reason:e.message,code:`KEY_ALGORITHM_MISMATCH`}}}if(x(u)){let e=n.signatureFormat,t;if(e===`jose`)try{let e=b(Buffer.from(s,`base64url`)).toString(`base64url`);t=T[u].verify(m,y,e)}catch{t=!1}else if(e===`der`)t=T[u].verify(m,y,s);else if(t=T[u].verify(m,y,s),!t)try{let e=Buffer.from(s,`base64url`);if(e.length===v(u)){let n=b(e).toString(`base64url`);t=T[u].verify(m,y,n)}}catch{}if(!t)return{valid:!1,error:{reason:`Signature verification failed`,code:`INVALID_SIGNATURE`}}}else{let e=!1;try{e=T[u].verify(m,y,s)}catch{e=!1}if(!e)return{valid:!1,error:{reason:`Signature verification failed`,code:`INVALID_SIGNATURE`}}}let S=Math.floor(Date.now()/1e3),C=n.clockSkew??0;if(!n.ignoreExpiration&&o.exp!==void 0&&S>o.exp+C)return{valid:!1,error:{reason:`Token expired`,code:`TOKEN_EXPIRED`}};if(o.nbf!==void 0&&S+C<o.nbf)return{valid:!1,error:{reason:`Token not yet valid`,code:`TOKEN_NOT_ACTIVE`}};if(o.iat!==void 0&&S+C<o.iat)return{valid:!1,error:{reason:`Token issued in the future`,code:`TOKEN_FUTURE_ISSUED`}};if(n.maxTokenAge!==void 0&&o.iat===void 0)return{valid:!1,error:{reason:`Token missing required issued-at claim ("iat")`,code:`MISSING_IAT`}};if(n.maxTokenAge!==void 0&&o.iat!==void 0){let e=S-o.iat;if(e>n.maxTokenAge)return{valid:!1,error:{reason:`Token age (${e}s) exceeds maximum allowed age (${n.maxTokenAge}s)`,code:`TOKEN_TOO_OLD`}}}if(n.issuer!==void 0){if(o.iss===void 0)return{valid:!1,error:{reason:`Token missing required issuer claim ("iss")`,code:`MISSING_ISSUER`}};if(n.issuer!==o.iss)return{valid:!1,error:{reason:`Invalid token issuer: expected "${n.issuer}", got "${o.iss}"`,code:`INVALID_ISSUER`}}}if(n.subject!==void 0){if(o.sub===void 0)return{valid:!1,error:{reason:`Token missing required subject claim ("sub")`,code:`MISSING_SUBJECT`}};if(n.subject!==o.sub)return{valid:!1,error:{reason:`Invalid token subject: expected "${n.subject}", got "${o.sub}"`,code:`INVALID_SUBJECT`}}}if(n.audience!==void 0){let e=o.aud;if(e===void 0)return{valid:!1,error:{reason:`Token missing required audience claim ("aud")`,code:`MISSING_AUDIENCE`}};let t=Array.isArray(n.audience)?n.audience:[n.audience],r=Array.isArray(e)?e:[e];if(!t.some(e=>r.includes(e)))return{valid:!1,error:{reason:`Audience claim mismatch`,code:`INVALID_AUDIENCE`}}}if(n.jwtId!==void 0){if(o.jti===void 0)return{valid:!1,error:{reason:`Token missing required JWT ID claim ("jti")`,code:`MISSING_JTI`}};if(n.jwtId!==o.jti)return{valid:!1,error:{reason:`Invalid JWT ID: expected "${n.jwtId}", got "${o.jti}"`,code:`INVALID_JTI`}}}return{valid:!0,header:a,payload:o,signature:s}},N={sign:j,verify:M,decode:A,algorithms:T};function P(e){if(!e||typeof e!=`object`)throw Error(`Invalid KeyObject`);return e.export({format:`jwk`})}function F(e){if(!e||typeof e!=`object`)throw Error(`Invalid JWK`);switch(e.kty){case`oct`:if(!(`k`in e)||typeof e.k!=`string`)throw Error(`Invalid oct JWK: missing "k"`);return(0,c.createSecretKey)(Buffer.from(e.k,`base64url`));case`RSA`:case`EC`:case`OKP`:return`d`in e&&typeof e.d==`string`?(0,c.createPrivateKey)({format:`jwk`,key:e}):(0,c.createPublicKey)({format:`jwk`,key:e});default:throw Error(`Unsupported JWK key type: ${e.kty}`)}}function I(e){if(!e||typeof e!=`object`)throw Error(`Invalid KeyObject`);let t=(e.type===`private`?(0,c.createPublicKey)(e):e).export({format:`jwk`});return delete t.d,delete t.p,delete t.q,delete t.dp,delete t.dq,delete t.qi,t}function L(e,t=`sha256`){if(!e||typeof e!=`object`)throw Error(`Invalid JWK`);let n;switch(e.kty){case`RSA`:n={e:e.e,kty:e.kty,n:e.n};break;case`EC`:n={crv:e.crv,kty:e.kty,x:e.x,y:e.y};break;case`OKP`:n={crv:e.crv,kty:e.kty,x:e.x};break;case`oct`:n={k:e.k,kty:e.kty};break;default:throw Error(`Unsupported JWK key type: ${e.kty}`)}let r=JSON.stringify(Object.keys(n).sort().reduce((e,t)=>(e[t]=n[t],e),{}));return(0,c.createHash)(t).update(r).digest(`base64url`)}function R(e){var t;if((t=e.x5c)!=null&&t.length)return(0,c.createHash)(`sha1`).update(Buffer.from(e.x5c[0],`base64`)).digest(`base64url`)}var z={export:P,import:F,toPublic:I,thumbprint:L};function B(e,t){if(!e||!Array.isArray(e.keys))throw Error(`Invalid JWKS`);let n;if(t&&(n=e.keys.find(e=>e.kid===t)),!n&&e.keys.length===1&&(n=e.keys[0]),!n)throw Error(`Key not found in JWKS`);return F(n)}function V(e){return{keys:H(...e.keys)}}function H(...e){return e.map(e=>{let t={...e,kid:e.kid??L(e),x5t:e.x5t??R(e)};return Object.defineProperty(t,"toKeyObject",{enumerable:!1,configurable:!1,writable:!1,value:()=>F(t)}),t})}var U=async(e,t={})=>{let n=typeof e==`string`?e:e.toString(),r=t.fetch??globalThis.fetch,i=Math.max(0,t.ttl??3e5),a=Math.max(0,t.timeoutMs??5e3),o=`/.well-known/jwks.json`;if(!r)throw Error(`No fetch implementation available`);let s=(()=>{if(t.endpointOverride){let e=t.endpointOverride;try{return new URL(e,n).toString()}catch{return e}}return t.overrideEndpointCheck||n.endsWith(o)?n:`${n.replace(/\/+$/,``)}${o}`})(),c=(()=>{if(t.cache)return t.cache;let e;return{get:()=>e,set:(t,n)=>{e=n}}})(),l,u=0,d,f=0,p=async e=>{if(d)return d;d=(async()=>{let e=new AbortController,t;a>0&&(t=setTimeout(()=>e.abort(),a));let n;try{n=await r(s,{signal:e.signal})}catch(t){throw e.signal.aborted?Error(`JWKS fetch timed out after ${a}ms`):t}finally{t&&clearTimeout(t)}if(!n.ok)throw Error(`Failed to fetch JWKS: ${n.status} ${n.statusText}`);let i=await n.json();if(!i||typeof i!=`object`||!Array.isArray(i.keys))throw Error(`Invalid JWKS`);return V(i)})();try{let e=await d;return l=e,await c.set(s,e),f=0,i>0&&(u=Date.now()+i),e}catch(t){if(!e||!l)throw t;if(f+=1,i>0){let e=Math.min(Math.max(i,3e4)*2**(f-1),9e5);u=Date.now()+e}return console.warn(`JWKS refresh failed for "${s}", using stale cache.`,t),l}finally{d=void 0}};l=await c.get(s),l?(l=V(l),i>0&&(u=Date.now()+i)):l=await p(!1);let m={async list(){return i>0&&Date.now()>=u&&await p(!0),H(...l.keys)},async refresh(){return await p(!1),m},async key(e){let t=(await m.list()).find(t=>t.kid===e);if(t)return H(t)[0]},async find(e){let t=await m.list(),n=Object.entries(e);return n.length===0?H(...t):H(...t.filter(e=>n.every(([t,n])=>{let r=e[t];return Array.isArray(n)?Array.isArray(r)&&r.length===n.length&&r.every((e,t)=>e===n[t]):r===n})))},async findFirst(e){return m.find(e).then(([e])=>e)},export(){return l}};return m},W={toKeyObject:B,normalize:V,fromWeb:U};exports.AutodetectAlgorithm=D,exports.JWK=z,exports.JWKS=W,exports.JWKSToKeyObject=B,exports.JWT=N,exports.SignatureAlgorithm=T,exports.SupportedAlgorithms=E,exports.base64Url=l,exports.computeX5T=R,exports.decode=A,exports.exportJWK=P,exports.fromWeb=U,exports.getJWKThumbprint=L,exports.importJWK=F,exports.normalizeJWK=H,exports.normalizeJWKS=V,exports.sign=j,exports.toPublicJWK=I,exports.verify=M;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/jwt/index.ts","../src/jwks/index.ts"],"sourcesContent":["import crypto, {\n createHmac,\n createSign,\n createVerify,\n createPrivateKey,\n createPublicKey,\n createSecretKey,\n sign as cryptoSign,\n verify as cryptoVerify,\n timingSafeEqual,\n type KeyLike,\n type KeyObject\n} from 'crypto';\n\n// Base64URL helpers (padding-safe)\nexport const base64Url = {\n encode: (input: string | Buffer): string => Buffer.from(input).toString('base64url'),\n decode: (input: string): string => Buffer.from(input, 'base64url').toString()\n};\n\n/**\n * Timing-safe string comparison to prevent timing attacks\n * @param a\n * @param b\n */\nconst timingSafeCompare = (a: string, b: string): boolean => {\n if (a.length !== b.length) {\n return false;\n }\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n};\n\n// Standard JWT payload claims\nexport interface JWTPayload {\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Subject\n */\n sub?: string;\n /**\n * Audience\n */\n aud?: string | string[];\n /**\n * Expiration Time (as UNIX timestamp)\n */\n exp?: number;\n /**\n * Not Before (as UNIX timestamp)\n */\n nbf?: number;\n /**\n * Issued At (as UNIX timestamp)\n */\n iat?: number;\n /**\n * JWT ID\n */\n jti?: string;\n /**\n * Session ID\n */\n sid?: string;\n\n /**\n * Custom claims\n */\n [key: string]: unknown;\n}\n\nexport interface JWTHeader {\n alg: string; // Allow unknown algs during decode\n typ?: string;\n kid?: string;\n crit?: string[];\n [key: string]: unknown;\n}\n\nexport interface JWT {\n header: JWTHeader;\n payload: JWTPayload;\n signature: string;\n}\n\nconst BASE64URL_SEGMENT_REGEX = /^[A-Za-z0-9_-]+$/;\n\nfunction isPlainObject(input: unknown): input is Record<string, unknown> {\n return typeof input === 'object' && input !== null && !Array.isArray(input);\n}\n\nfunction isFiniteNumber(input: unknown): input is number {\n return typeof input === 'number' && Number.isFinite(input);\n}\n\nfunction isStringArray(input: unknown): input is string[] {\n return Array.isArray(input) && input.every((value) => typeof value === 'string');\n}\n\nfunction validateRegisteredClaims(payload: JWTPayload): { reason: string; code: string } | null {\n const claimValidators: Array<{ claim: keyof JWTPayload; valid: boolean; expected: string }> = [\n {claim: 'iss', valid: payload.iss === undefined || typeof payload.iss === 'string', expected: 'string'},\n {claim: 'sub', valid: payload.sub === undefined || typeof payload.sub === 'string', expected: 'string'},\n {claim: 'jti', valid: payload.jti === undefined || typeof payload.jti === 'string', expected: 'string'},\n {claim: 'sid', valid: payload.sid === undefined || typeof payload.sid === 'string', expected: 'string'},\n {claim: 'iat', valid: payload.iat === undefined || isFiniteNumber(payload.iat), expected: 'number'},\n {claim: 'exp', valid: payload.exp === undefined || isFiniteNumber(payload.exp), expected: 'number'},\n {claim: 'nbf', valid: payload.nbf === undefined || isFiniteNumber(payload.nbf), expected: 'number'},\n ];\n\n for (const entry of claimValidators) {\n if (!entry.valid) {\n return {\n reason: `Invalid \"${entry.claim}\" claim: expected ${entry.expected}`,\n code: 'INVALID_CLAIM'\n };\n }\n }\n\n if (payload.aud !== undefined) {\n const isValidAudience = typeof payload.aud === 'string' || isStringArray(payload.aud);\n if (!isValidAudience) {\n return {\n reason: 'Invalid \"aud\" claim: expected string or string[]',\n code: 'INVALID_CLAIM'\n };\n }\n }\n\n return null;\n}\n\nfunction validateVerifyOptions(options: VerifyOptions): { reason: string; code: string } | null {\n if (options.signatureFormat !== undefined && options.signatureFormat !== 'der' && options.signatureFormat !== 'jose') {\n return {\n reason: 'Invalid signatureFormat option: expected \"der\" or \"jose\"',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.clockSkew !== undefined && (!isFiniteNumber(options.clockSkew) || options.clockSkew < 0)) {\n return {\n reason: 'Invalid clockSkew option: expected a non-negative finite number',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.maxTokenAge !== undefined && (!isFiniteNumber(options.maxTokenAge) || options.maxTokenAge < 0)) {\n return {\n reason: 'Invalid maxTokenAge option: expected a non-negative finite number',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.ignoreExpiration !== undefined && typeof options.ignoreExpiration !== 'boolean') {\n return {\n reason: 'Invalid ignoreExpiration option: expected boolean',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.issuer !== undefined && typeof options.issuer !== 'string') {\n return {\n reason: 'Invalid issuer option: expected string',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.subject !== undefined && typeof options.subject !== 'string') {\n return {\n reason: 'Invalid subject option: expected string',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.jwtId !== undefined && typeof options.jwtId !== 'string') {\n return {\n reason: 'Invalid jwtId option: expected string',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.audience !== undefined) {\n const isValidAudience = typeof options.audience === 'string' || isStringArray(options.audience);\n if (!isValidAudience) {\n return {\n reason: 'Invalid audience option: expected string or string[]',\n code: 'INVALID_OPTIONS'\n };\n }\n }\n\n if (options.algorithms !== undefined) {\n if (!Array.isArray(options.algorithms) || options.algorithms.length === 0) {\n return {\n reason: 'Invalid algorithms option: expected a non-empty array',\n code: 'INVALID_OPTIONS'\n };\n }\n\n const invalidAlgorithm = options.algorithms.find((alg) => !(alg in SignatureAlgorithm));\n if (invalidAlgorithm) {\n return {\n reason: `Invalid algorithms option: unsupported algorithm \"${invalidAlgorithm}\"`,\n code: 'INVALID_OPTIONS'\n };\n }\n }\n\n if (options.tokenTypes !== undefined) {\n if (!Array.isArray(options.tokenTypes) || options.tokenTypes.length === 0 || !isStringArray(options.tokenTypes)) {\n return {\n reason: 'Invalid tokenTypes option: expected a non-empty string[]',\n code: 'INVALID_OPTIONS'\n };\n }\n\n if (options.tokenTypes.some((type) => type.length === 0)) {\n return {\n reason: 'Invalid tokenTypes option: token types must not be empty',\n code: 'INVALID_OPTIONS'\n };\n }\n }\n\n return null;\n}\n\nfunction validateProtectedHeader(header: JWTHeader): { reason: string; code: string } | null {\n if (header.crit !== undefined) {\n if (!isStringArray(header.crit) || header.crit.length === 0) {\n return {\n reason: 'Invalid \"crit\" header: expected non-empty string[]',\n code: 'INVALID_HEADER'\n };\n }\n\n return {\n reason: `Unsupported critical header parameters: ${header.crit.join(', ')}`,\n code: 'UNSUPPORTED_CRITICAL_HEADER'\n };\n }\n\n return null;\n}\n\n\n//JOSE-helpers\nfunction joseLenForAlg(alg: string): number {\n switch (alg) {\n case 'ES256':\n case 'ES256K':\n return 64; // 32 + 32\n case 'ES384':\n return 96; // 48 + 48\n case 'ES512':\n return 132; // 66 + 66 (P-521)\n /* c8 ignore next 2 */\n default:\n throw new Error(`Unsupported ECDSA alg for JOSE conversion: ${alg}`);\n }\n}\n\nfunction derToJose(der: Buffer, outLen: number): Buffer {\n let i = 0;\n if (der[i++] !== 0x30) throw new Error('Invalid DER ECDSA signature');\n\n // seq length (short/long form)\n let seqLen = der[i++];\n if (seqLen & 0x80) {\n const n = seqLen & 0x7f;\n seqLen = 0;\n for (let k = 0; k < n; k++) seqLen = (seqLen << 8) | der[i++];\n }\n\n if (der[i++] !== 0x02) throw new Error('Invalid DER ECDSA signature (r)');\n const rLen = der[i++];\n let r = der.subarray(i, i + rLen);\n i += rLen;\n\n if (der[i++] !== 0x02) throw new Error('Invalid DER ECDSA signature (s)');\n const sLen = der[i++];\n let s = der.subarray(i, i + sLen);\n\n // strip leading zeros\n while (r.length > outLen / 2 && r[0] === 0x00) r = r.subarray(1);\n while (s.length > outLen / 2 && s[0] === 0x00) s = s.subarray(1);\n\n const rPad = Buffer.concat([Buffer.alloc(outLen / 2 - r.length, 0), r]);\n const sPad = Buffer.concat([Buffer.alloc(outLen / 2 - s.length, 0), s]);\n return Buffer.concat([rPad, sPad]);\n}\n\nfunction joseToDer(jose: Buffer): Buffer {\n const half = jose.length / 2;\n let r = jose.subarray(0, half);\n let s = jose.subarray(half);\n\n // trim leading zeros\n while (r.length > 1 && r[0] === 0x00 && (r[1] & 0x80) === 0) r = r.subarray(1);\n while (s.length > 1 && s[0] === 0x00 && (s[1] & 0x80) === 0) s = s.subarray(1);\n\n // if high bit set, prepend 0x00\n if (r[0] & 0x80) r = Buffer.concat([Buffer.from([0x00]), r]);\n if (s[0] & 0x80) s = Buffer.concat([Buffer.from([0x00]), s]);\n\n const rPart = Buffer.concat([Buffer.from([0x02, r.length]), r]);\n const sPart = Buffer.concat([Buffer.from([0x02, s.length]), s]);\n\n const seqLen = rPart.length + sPart.length;\n\n let lenBytes: Buffer;\n if (seqLen < 0x80) {\n lenBytes = Buffer.from([seqLen]);\n } else {\n const tmp: number[] = [];\n let n = seqLen;\n while (n > 0) {\n tmp.unshift(n & 0xff);\n n >>= 8;\n }\n lenBytes = Buffer.from([0x80 | tmp.length, ...tmp]);\n }\n\n return Buffer.concat([Buffer.from([0x30]), lenBytes, rPart, sPart]);\n}\n\nfunction isEcdsaAlg(alg: string): boolean {\n return alg === 'ES256' || alg === 'ES384' || alg === 'ES512' || alg === 'ES256K';\n}\n\ntype SignatureAlgorithmImplementation = {\n sign: (data: string | NodeJS.ArrayBufferView, secret: KeyLike) => string;\n verify: (data: string | NodeJS.ArrayBufferView, secret: KeyLike, signature: string) => boolean;\n};\n\ntype SignatureAlgorithmsMap = {\n HS256: SignatureAlgorithmImplementation;\n HS384: SignatureAlgorithmImplementation;\n HS512: SignatureAlgorithmImplementation;\n RS256: SignatureAlgorithmImplementation;\n RS384: SignatureAlgorithmImplementation;\n RS512: SignatureAlgorithmImplementation;\n ES256: SignatureAlgorithmImplementation;\n ES384: SignatureAlgorithmImplementation;\n ES512: SignatureAlgorithmImplementation;\n ES256K: SignatureAlgorithmImplementation;\n PS256: SignatureAlgorithmImplementation;\n PS384: SignatureAlgorithmImplementation;\n PS512: SignatureAlgorithmImplementation;\n EdDSA: SignatureAlgorithmImplementation;\n};\n\nconst createHmacAlgorithm = (algorithm: string): SignatureAlgorithmImplementation => ({\n sign: (data: string | NodeJS.ArrayBufferView, secret: KeyLike): string =>\n createHmac(algorithm, secret).update(data).digest('base64url'),\n verify: (data: string | NodeJS.ArrayBufferView, secret: KeyLike, signature: string): boolean => {\n const expected = createHmac(algorithm, secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n});\n\nconst createVerifyAlgorithm = (algorithm: string): SignatureAlgorithmImplementation => ({\n sign: (data: string | NodeJS.ArrayBufferView, secret: KeyLike): string =>\n createSign(algorithm).update(data).end().sign(secret).toString('base64url'),\n verify: (data: string | NodeJS.ArrayBufferView, secret: KeyLike, signature: string): boolean => {\n try {\n return createVerify(algorithm)\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n});\n\nconst createPssAlgorithm = (algorithm: string, saltLength: number): SignatureAlgorithmImplementation => ({\n sign: (data: string | NodeJS.ArrayBufferView, secret: KeyLike): string =>\n createSign(algorithm)\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength\n })\n .toString('base64url'),\n verify: (data: string | NodeJS.ArrayBufferView, secret: KeyLike, signature: string): boolean => {\n try {\n return createVerify(algorithm)\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n});\n\nconst edDsaAlgorithm: SignatureAlgorithmImplementation = {\n sign: (data: string | NodeJS.ArrayBufferView, secret: KeyLike): string =>\n cryptoSign(null, typeof data === 'string' ? Buffer.from(data, 'utf8') : data, secret)\n .toString('base64url'),\n verify: (data: string | NodeJS.ArrayBufferView, secret: KeyLike, signature: string): boolean => {\n try {\n return cryptoVerify(\n null,\n typeof data === 'string' ? Buffer.from(data, 'utf8') : data,\n secret,\n Buffer.from(signature, 'base64url')\n );\n } catch {\n return false;\n }\n }\n};\n\n\n// Signature algorithms\nexport const SignatureAlgorithm: SignatureAlgorithmsMap = {\n // HMAC\n HS256: createHmacAlgorithm('sha256'),\n HS384: createHmacAlgorithm('sha384'),\n HS512: createHmacAlgorithm('sha512'),\n\n // RSA (DER-encoded signatures, base64url)\n RS256: createVerifyAlgorithm('RSA-SHA256'),\n RS384: createVerifyAlgorithm('RSA-SHA384'),\n RS512: createVerifyAlgorithm('RSA-SHA512'),\n\n // ECDSA (Node/OpenSSL emits DER; sign() converts to JOSE by default for JWTs)\n ES256: createVerifyAlgorithm('SHA256'),\n ES384: createVerifyAlgorithm('SHA384'),\n ES512: createVerifyAlgorithm('SHA512'),\n ES256K: createVerifyAlgorithm('SHA256'),\n PS256: createPssAlgorithm('RSA-SHA256', 32),\n PS384: createPssAlgorithm('RSA-SHA384', 48),\n PS512: createPssAlgorithm('RSA-SHA512', 64),\n EdDSA: edDsaAlgorithm\n} as const;\n\nexport type SupportedAlgorithm = keyof typeof SignatureAlgorithm;\n\nexport const SupportedAlgorithms = Object.keys(SignatureAlgorithm) as Array<SupportedAlgorithm>;\n\n/**\n * Autodetection of algorithm for KeyObjects\n * @param key\n * @constructor\n */\nexport function AutodetectAlgorithm(key: KeyObject): SupportedAlgorithm {\n if (key.type === 'secret') return 'HS256';\n if (key.type !== 'private') throw new Error('Only private or symmetric keys can be used to sign JWTs');\n\n const asymKeyType = key.asymmetricKeyType;\n const details = key.asymmetricKeyDetails;\n\n switch (asymKeyType) {\n case 'rsa':\n return 'RS256';\n case 'rsa-pss': {\n const hash = details?.hashAlgorithm ?? 'sha256';\n switch (hash) {\n case 'sha256':\n return 'PS256';\n case 'sha384':\n return 'PS384';\n case 'sha512':\n return 'PS512';\n default:\n throw new Error(`Unsupported RSA-PSS hash algorithm: ${hash}`);\n }\n }\n case 'ec': {\n const curve = details?.namedCurve;\n switch (curve) {\n case 'P-256':\n case 'prime256v1':\n return 'ES256';\n case 'P-384':\n case 'secp384r1':\n return 'ES384';\n case 'P-521':\n case 'secp521r1':\n return 'ES512';\n case 'secp256k1':\n return 'ES256K';\n default:\n throw new Error(`Unsupported EC curve: ${curve}`);\n }\n }\n case 'ed25519':\n return 'EdDSA';\n default:\n throw new Error(`Unsupported asymmetric key type: ${asymKeyType}`);\n }\n}\n\n/**\n * Normalize KeyLike input to a KeyObject\n * @param key\n */\nfunction toKeyObject(key: KeyLike, purpose: 'sign' | 'verify'): KeyObject {\n // Already a KeyObject (private, public, or secret)\n if (typeof key === 'object' && 'type' in key) return key as KeyObject;\n\n // A private key can sign and its public component can verify.\n try {\n return purpose === 'sign' ? createPrivateKey(key) : createPublicKey(key);\n } catch {\n if (purpose === 'sign') {\n // Do not silently reinterpret a PEM/DER public key as an HMAC secret.\n try {\n createPublicKey(key);\n } catch {\n // The input is not a public key; it may still be a symmetric secret.\n if (typeof key === 'string') return createSecretKey(Buffer.from(key, 'utf8'));\n if (Buffer.isBuffer(key)) return createSecretKey(key);\n throw new Error('Unsupported key type');\n }\n throw new Error('A public key cannot be used to sign JWTs');\n }\n\n if (typeof key === 'string') return createSecretKey(Buffer.from(key, 'utf8'));\n if (Buffer.isBuffer(key)) return createSecretKey(key);\n throw new Error('Unsupported key type');\n }\n}\n\nfunction assertKeySupportsAlgorithm(key: KeyObject, alg: SupportedAlgorithm, purpose: 'sign' | 'verify'): void {\n if (alg.startsWith('HS')) {\n if (key.type !== 'secret') throw new Error(`${alg} requires a symmetric secret key`);\n return;\n }\n\n if (purpose === 'sign' && key.type !== 'private') {\n throw new Error(`${alg} requires a private key for signing`);\n }\n if (purpose === 'verify' && key.type !== 'public' && key.type !== 'private') {\n throw new Error(`${alg} requires a public or private key for verification`);\n }\n\n const keyType = key.asymmetricKeyType;\n if (alg.startsWith('RS') && keyType !== 'rsa') {\n throw new Error(`${alg} requires an RSA key`);\n }\n if (alg.startsWith('PS') && keyType !== 'rsa' && keyType !== 'rsa-pss') {\n throw new Error(`${alg} requires an RSA or RSA-PSS key`);\n }\n if (alg === 'EdDSA' && keyType !== 'ed25519') {\n throw new Error('EdDSA requires an Ed25519 key');\n }\n if (isEcdsaAlg(alg)) {\n const curve = key.asymmetricKeyDetails?.namedCurve;\n let expectedCurve: string[] = [];\n switch (alg) {\n case 'ES256':\n expectedCurve = ['P-256', 'prime256v1'];\n break;\n case 'ES384':\n expectedCurve = ['P-384', 'secp384r1'];\n break;\n case 'ES512':\n expectedCurve = ['P-521', 'secp521r1'];\n break;\n case 'ES256K':\n expectedCurve = ['secp256k1'];\n break;\n }\n if (keyType !== 'ec' || !expectedCurve.includes(curve ?? '')) {\n throw new Error(`${alg} requires its matching EC curve`);\n }\n }\n}\n\n/**\n * Decode a JWT string into its parts (without verification)\n * @param token\n */\nexport const decode = (token: string): JWT => {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT: must contain exactly 3 parts separated by \".\"');\n }\n\n const [headerPart, payloadPart, signature] = parts;\n\n if (!headerPart || !payloadPart || !signature) {\n throw new Error('Invalid JWT: empty part detected');\n }\n\n if (!BASE64URL_SEGMENT_REGEX.test(headerPart) || !BASE64URL_SEGMENT_REGEX.test(payloadPart) || !BASE64URL_SEGMENT_REGEX.test(signature)) {\n throw new Error('Invalid JWT: non-base64url characters detected');\n }\n\n try {\n const decodedHeader = JSON.parse(base64Url.decode(headerPart));\n const decodedPayload = JSON.parse(base64Url.decode(payloadPart));\n\n if (!isPlainObject(decodedHeader) || !isPlainObject(decodedPayload)) {\n throw new Error('header and payload must be JSON objects');\n }\n\n const header = decodedHeader as unknown as JWTHeader;\n const payload = decodedPayload as JWTPayload;\n\n if (typeof header.alg !== 'string' || header.alg.length === 0) {\n throw new Error('header.alg must be a non-empty string');\n }\n if (header.typ !== undefined && typeof header.typ !== 'string') {\n throw new Error('header.typ must be a string');\n }\n if (header.kid !== undefined && typeof header.kid !== 'string') {\n throw new Error('header.kid must be a string');\n }\n if (header.crit !== undefined && (!isStringArray(header.crit) || header.crit.length === 0)) {\n throw new Error('header.crit must be a non-empty string[]');\n }\n\n return {header, payload, signature};\n } catch (err) {\n throw new Error(`Invalid JWT: malformed header or payload (${(err as Error).message})`);\n }\n}\n\nexport type SignOptions = {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n /**\n * default 'jose' for ECDSA JWTs, 'der' otherwise\n */\n signatureFormat?: 'der' | 'jose';\n}\n\n/**\n * Sign a JWT\n * @param payload\n * @param secret\n * @param options\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: SignOptions = {}\n): string => {\n const key = toKeyObject(secret, 'sign');\n const alg = options.alg ?? AutodetectAlgorithm(key);\n const signatureFormat = options.signatureFormat ?? (isEcdsaAlg(alg) ? 'jose' : 'der');\n const typ = options.typ ?? 'JWT';\n\n if (!(alg in SignatureAlgorithm)) throw new Error(`Unsupported algorithm: ${alg}`);\n assertKeySupportsAlgorithm(key, alg, 'sign');\n\n const header: JWTHeader = {alg, typ};\n if (options.kid) header.kid = options.kid;\n\n const headerEncoded = base64Url.encode(JSON.stringify(header));\n const payloadEncoded = base64Url.encode(JSON.stringify(payload));\n\n const signingInput = `${headerEncoded}.${payloadEncoded}`;\n\n // Node/OpenSSL produces DER signatures for ECDSA; convert to JOSE for JWT output by default.\n let signature = SignatureAlgorithm[alg].sign(signingInput, key);\n\n // If ES* and caller requested JOSE, convert the DER signature bytes to JOSE bytes\n if (signatureFormat === 'jose' && isEcdsaAlg(alg)) {\n const der = Buffer.from(signature, 'base64url');\n const jose = derToJose(der, joseLenForAlg(alg));\n signature = jose.toString('base64url');\n }\n\n return `${headerEncoded}.${payloadEncoded}.${signature}`;\n\n};\n\nexport type VerifyOptions = {\n algorithms?: SupportedAlgorithm[]; // Whitelist of allowed algorithms\n /** Allowed protected-header `typ` values. Defaults to `['JWT']`. A missing `typ` remains valid. */\n tokenTypes?: string[];\n issuer?: string;\n subject?: string;\n audience?: string | string[];\n jwtId?: string;\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n maxTokenAge?: number; // Maximum age in seconds; requires an iat claim\n signatureFormat?: 'der' | 'jose';\n};\n\n/**\n * Verify and validate a JWT\n * @param token\n * @param secret\n * @param options\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: VerifyOptions = {}\n):\n | { valid: true; header: JWTHeader; payload: JWTPayload; signature: string }\n | { valid: false; error: { reason: string; code: string } } => {\n const invalidOptions = validateVerifyOptions(options);\n if (invalidOptions) {\n return {\n valid: false,\n error: invalidOptions\n };\n }\n\n let decoded: JWT;\n try {\n decoded = decode(token);\n } catch (err) {\n return {\n valid: false,\n error: {\n reason: (err as Error).message,\n code: 'INVALID_TOKEN'\n }\n };\n }\n\n const {header, payload, signature} = decoded;\n const invalidHeader = validateProtectedHeader(header);\n if (invalidHeader) {\n return {\n valid: false,\n error: invalidHeader\n };\n }\n\n const invalidClaims = validateRegisteredClaims(payload);\n if (invalidClaims) {\n return {\n valid: false,\n error: invalidClaims\n };\n }\n\n // Validate algorithm\n const alg = header.alg as SupportedAlgorithm;\n if (!(alg in SignatureAlgorithm)) {\n return {\n valid: false,\n error: {\n reason: `Unsupported or unknown algorithm: ${header.alg}`,\n code: 'INVALID_ALGORITHM'\n }\n };\n }\n\n // Algorithm whitelist validation (prevents algorithm confusion attacks)\n if (options.algorithms && options.algorithms.length > 0) {\n if (!options.algorithms.includes(alg)) {\n return {\n valid: false,\n error: {\n reason: `Algorithm \"${alg}\" is not in the allowed algorithms list`,\n code: 'ALGORITHM_NOT_ALLOWED'\n }\n };\n }\n }\n\n // JWT permits omitting `typ`. When present, it must match the caller's\n // explicit allowlist or the secure default of only `JWT`.\n const tokenTypes = options.tokenTypes ?? ['JWT'];\n if (header.typ !== undefined && !tokenTypes.includes(header.typ)) {\n return {\n valid: false,\n error: {\n reason: `Invalid token type: expected one of ${tokenTypes.map((type) => `'${type}'`).join(', ')}, got '${header.typ}'`,\n code: 'INVALID_TYPE'\n }\n };\n }\n\n // Verify signature against the exact original JWT signing input.\n const [headerPart, payloadPart] = token.split('.');\n const signingInput = `${headerPart}.${payloadPart}`;\n\n let key: KeyObject;\n try {\n key = toKeyObject(secret, 'verify');\n assertKeySupportsAlgorithm(key, alg, 'verify');\n } catch (error) {\n return {\n valid: false,\n error: {\n reason: (error as Error).message,\n code: 'KEY_ALGORITHM_MISMATCH'\n }\n };\n }\n\n if (!isEcdsaAlg(alg)) {\n // non-ES* algorithms unchanged\n let isValidSignature = false;\n try {\n isValidSignature = SignatureAlgorithm[alg].verify(signingInput, key, signature);\n } catch {\n isValidSignature = false;\n }\n if (!isValidSignature) {\n return {valid: false, error: {reason: \"Signature verification failed\", code: 'INVALID_SIGNATURE'}};\n }\n } else {\n // ES* algorithms accept strict DER/JOSE modes or auto-detect for interoperability.\n const format = options.signatureFormat; // undefined means \"auto\"\n\n let ok: boolean;\n\n // 1) If explicitly JOSE -> convert to DER for verification\n if (format === 'jose') {\n try {\n const jose = Buffer.from(signature, 'base64url');\n const derSigB64Url = joseToDer(jose).toString('base64url');\n ok = SignatureAlgorithm[alg].verify(signingInput, key, derSigB64Url);\n } catch {\n ok = false;\n }\n }\n // 2) If explicitly DER -> verify as-is\n else if (format === 'der') {\n ok = SignatureAlgorithm[alg].verify(signingInput, key, signature);\n }\n // 3) Auto-detect: try DER first, then JOSE\n else {\n ok = SignatureAlgorithm[alg].verify(signingInput, key, signature);\n if (!ok) {\n try {\n const jose = Buffer.from(signature, 'base64url');\n // quick sanity: only attempt conversion if size matches expected\n if (jose.length === joseLenForAlg(alg)) {\n const derSigB64Url = joseToDer(jose).toString('base64url');\n ok = SignatureAlgorithm[alg].verify(signingInput, key, derSigB64Url);\n }\n } catch {\n // ignore\n }\n }\n }\n\n if (!ok) {\n return {valid: false, error: {reason: \"Signature verification failed\", code: 'INVALID_SIGNATURE'}};\n }\n }\n\n // Time validation\n const now = Math.floor(Date.now() / 1000);\n const skew = options.clockSkew ?? 0;\n\n if (!options.ignoreExpiration) {\n if (payload.exp !== undefined && now > payload.exp + skew) {\n return {\n valid: false,\n error: {\n reason: 'Token expired',\n code: 'TOKEN_EXPIRED'\n }\n };\n }\n }\n\n if (payload.nbf !== undefined && now + skew < payload.nbf) {\n return {\n valid: false,\n error: {\n reason: 'Token not yet valid',\n code: 'TOKEN_NOT_ACTIVE'\n }\n };\n }\n\n if (payload.iat !== undefined && now + skew < payload.iat) {\n return {\n valid: false,\n error: {\n reason: 'Token issued in the future',\n code: 'TOKEN_FUTURE_ISSUED'\n }\n };\n }\n\n // Maximum token age validation\n if (options.maxTokenAge !== undefined && payload.iat === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required issued-at claim (\"iat\")',\n code: 'MISSING_IAT'\n }\n };\n }\n\n if (options.maxTokenAge !== undefined && payload.iat !== undefined) {\n const tokenAge = now - payload.iat;\n if (tokenAge > options.maxTokenAge) {\n return {\n valid: false,\n error: {\n reason: `Token age (${tokenAge}s) exceeds maximum allowed age (${options.maxTokenAge}s)`,\n code: 'TOKEN_TOO_OLD'\n }\n };\n }\n }\n\n // --- Claim validations (only if options provided) ---\n\n // Issuer (`iss`)\n if (options.issuer !== undefined) {\n if (payload.iss === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required issuer claim (\"iss\")',\n code: 'MISSING_ISSUER'\n }\n };\n }\n if (options.issuer !== payload.iss) {\n return {\n valid: false,\n error: {\n reason: `Invalid token issuer: expected \"${options.issuer}\", got \"${payload.iss}\"`,\n code: 'INVALID_ISSUER'\n }\n };\n }\n }\n\n // Subject (`sub`)\n if (options.subject !== undefined) {\n if (payload.sub === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required subject claim (\"sub\")',\n code: 'MISSING_SUBJECT'\n }\n };\n }\n if (options.subject !== payload.sub) {\n return {\n valid: false,\n error: {\n reason: `Invalid token subject: expected \"${options.subject}\", got \"${payload.sub}\"`,\n code: 'INVALID_SUBJECT'\n }\n };\n }\n }\n\n // Audience (`aud`)\n if (options.audience !== undefined) {\n const aud = payload.aud;\n if (aud === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required audience claim (\"aud\")',\n code: 'MISSING_AUDIENCE'\n }\n };\n }\n\n const expectedAud = Array.isArray(options.audience) ? options.audience : [options.audience];\n const tokenAud = Array.isArray(aud) ? aud : [aud];\n\n const hasMatch = expectedAud.some(a => tokenAud.includes(a));\n if (!hasMatch) {\n return {\n valid: false,\n error: {\n reason: 'Audience claim mismatch',\n code: 'INVALID_AUDIENCE'\n }\n };\n }\n }\n\n // JWT ID (`jti`)\n if (options.jwtId !== undefined) {\n if (payload.jti === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required JWT ID claim (\"jti\")',\n code: 'MISSING_JTI'\n }\n };\n }\n if (options.jwtId !== payload.jti) {\n return {\n valid: false,\n error: {\n reason: `Invalid JWT ID: expected \"${options.jwtId}\", got \"${payload.jti}\"`,\n code: 'INVALID_JTI'\n }\n };\n }\n }\n\n return {valid: true, header, payload, signature};\n};\n\n//namespace export\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n} as const;\n","import {\n createPrivateKey,\n createPublicKey,\n createSecretKey,\n createHash,\n type KeyObject\n} from 'crypto';\n\n// JWK Types\nexport type JWK =\n | RSAJWK\n | ECJWK\n | OKPJWK\n | OctJWK;\n\nexport type JWKWithHelpers = JWK & {\n toKeyObject(): KeyObject;\n};\n\nexport interface BaseJWK {\n kty: string;\n kid?: string;\n alg?: string;\n use?: 'sig' | 'enc';\n key_ops?: Array<'sign' | 'verify'>;\n x5c?: string[]; // X.509 cert chain\n x5t?: string; // Base64url thumbprint\n}\n\nexport interface RSAJWK extends BaseJWK {\n kty: 'RSA';\n n: string;\n e: string;\n d?: string;\n p?: string;\n q?: string;\n dp?: string;\n dq?: string;\n qi?: string;\n}\n\nexport interface ECJWK extends BaseJWK {\n kty: 'EC';\n crv: 'P-256' | 'P-384' | 'P-521' | 'secp256k1';\n x: string;\n y: string;\n d?: string;\n}\n\nexport interface OKPJWK extends BaseJWK {\n kty: 'OKP';\n crv: 'Ed25519';\n x: string;\n d?: string;\n}\n\nexport interface OctJWK extends BaseJWK {\n kty: 'oct';\n k: string;\n}\n\n/**\n * Export KeyObject to JWK\n * @param key\n */\nexport function exportJWK(key: KeyObject): JWK {\n if (!key || typeof key !== 'object') throw new Error('Invalid KeyObject');\n return key.export({format: 'jwk'}) as JWK;\n}\n\n/**\n * Import JWK to KeyObject\n * @param jwk\n */\nexport function importJWK(jwk: JWK): KeyObject {\n if (!jwk || typeof jwk !== 'object') throw new Error('Invalid JWK');\n\n switch (jwk.kty) {\n case 'oct': {\n if (!('k' in jwk) || typeof jwk.k !== 'string') {\n throw new Error('Invalid oct JWK: missing \"k\"');\n }\n\n return createSecretKey(Buffer.from(jwk.k, 'base64url'));\n }\n\n case 'RSA':\n case 'EC':\n case 'OKP': {\n // private key\n if ('d' in jwk && typeof (jwk as any).d === 'string') {\n // @ts-ignore\n return createPrivateKey({format: 'jwk', key: jwk});\n }\n\n // public key\n // @ts-ignore\n return createPublicKey({format: 'jwk', key: jwk});\n }\n\n default:\n throw new Error(`Unsupported JWK key type: ${(jwk as any).kty}`);\n }\n}\n\n/**\n * Export public-only JWK\n * @param key\n */\nexport function toPublicJWK(key: KeyObject): JWK {\n if (!key || typeof key !== 'object') {\n throw new Error('Invalid KeyObject');\n }\n\n const publicKey =\n key.type === 'private'\n ? createPublicKey(key)\n : key;\n\n const jwk = publicKey.export({format: 'jwk'}) as JWK;\n\n // Ensure private fields are not present\n delete (jwk as any).d;\n delete (jwk as any).p;\n delete (jwk as any).q;\n delete (jwk as any).dp;\n delete (jwk as any).dq;\n delete (jwk as any).qi;\n return jwk;\n}\n\n/**\n * RFC 7638 JWK thumbprint\n * @param jwk\n * @param hashAlg\n */\nexport function getJWKThumbprint(jwk: JWK, hashAlg: 'sha256' = 'sha256'): string {\n if (!jwk || typeof jwk !== 'object') {\n throw new Error('Invalid JWK');\n }\n\n let fields: Record<string, string>;\n\n switch (jwk.kty) {\n case 'RSA':\n fields = {e: jwk.e, kty: jwk.kty, n: jwk.n};\n break;\n\n case 'EC':\n fields = {crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y};\n break;\n\n case 'OKP':\n fields = {crv: jwk.crv, kty: jwk.kty, x: jwk.x};\n break;\n\n case 'oct':\n fields = {k: jwk.k, kty: jwk.kty};\n break;\n\n default:\n throw new Error(`Unsupported JWK key type: ${(jwk as any).kty}`);\n }\n\n // Lexicographically sorted JSON\n const json = JSON.stringify(\n Object.keys(fields)\n .sort()\n .reduce((acc, k) => {\n acc[k] = fields[k];\n return acc;\n }, {} as Record<string, string>)\n );\n\n return createHash(hashAlg)\n .update(json)\n .digest('base64url');\n}\n\n\n/**\n * Compute x5t (SHA-1) from first cert in x5c if not set\n * @param jwk\n */\nexport function computeX5T(jwk: JWK): string | undefined {\n if (!jwk.x5c?.length) return undefined;\n return createHash('sha1').update(Buffer.from(jwk.x5c[0], 'base64')).digest('base64url');\n}\n\nexport const JWK = {\n export: exportJWK,\n import: importJWK,\n toPublic: toPublicJWK,\n thumbprint: getJWKThumbprint,\n}\n\nexport interface JWKS {\n keys: JWK[];\n}\n\nexport interface JWKSResolver {\n list(): Promise<JWKWithHelpers[]>;\n refresh(): Promise<JWKSResolver>;\n key(kid: string): Promise<JWKWithHelpers | undefined>;\n find(input: Partial<BaseJWK>): Promise<JWKWithHelpers[]>;\n findFirst(input: Partial<BaseJWK>): Promise<JWKWithHelpers | undefined>;\n export(): JWKS | undefined;\n}\n\n/**\n * Convert JWKS specific key of first key to KeyObject\n * @param jwks\n * @param kid\n * @constructor\n */\nexport function JWKSToKeyObject(\n jwks: JWKS,\n kid?: string\n): KeyObject {\n if (!jwks || !Array.isArray(jwks.keys)) throw new Error('Invalid JWKS');\n\n let jwk: JWK | undefined;\n\n if (kid) jwk = jwks.keys.find(k => k.kid === kid);\n\n // Fallback: single-key JWKS\n if (!jwk && jwks.keys.length === 1) jwk = jwks.keys[0];\n\n if (!jwk) throw new Error('Key not found in JWKS');\n return importJWK(jwk);\n}\n\n/**\n * Normalize JWKS\n * @param jwks\n */\nexport function normalizeJWKS(jwks: JWKS): JWKS {\n return {\n keys: normalizeJWK(...jwks.keys)\n };\n}\n\nexport function normalizeJWK(...keys: JWK[]): JWKWithHelpers[] {\n return keys.map((jwk) => {\n const normalized = {\n ...jwk,\n kid: jwk.kid ?? getJWKThumbprint(jwk),\n x5t: jwk.x5t ?? computeX5T(jwk)\n } as JWKWithHelpers;\n\n // Keep helper API out of object enumeration/serialization.\n Object.defineProperty(normalized, 'toKeyObject', {\n enumerable: false,\n configurable: false,\n writable: false,\n value: () => importJWK(normalized)\n });\n\n return normalized;\n })\n}\n\nexport const fromWeb = async (\n url: string | URL,\n options: Partial<{\n fetch: typeof fetch;\n ttl: number;\n timeoutMs: number;\n endpointOverride: string;\n overrideEndpointCheck: boolean;\n cache: {\n get: (key: string) => JWKS | undefined | Promise<JWKS | undefined>;\n set: (key: string, value: JWKS) => void | Promise<void>;\n };\n }> = {}\n): Promise<JWKSResolver> => {\n const baseUrl = typeof url === 'string' ? url : url.toString();\n const fetchFn = options.fetch ?? globalThis.fetch;\n const ttl = Math.max(0, options.ttl ?? 5 * 60_000);\n const timeoutMs = Math.max(0, options.timeoutMs ?? 5_000);\n const wellKnownPath = '/.well-known/jwks.json';\n\n if (!fetchFn) {\n throw new Error('No fetch implementation available');\n }\n\n const endpoint = (() => {\n if (options.endpointOverride) {\n const override = options.endpointOverride;\n try {\n return new URL(override, baseUrl).toString();\n } catch {\n return override;\n }\n }\n\n if (options.overrideEndpointCheck) {\n return baseUrl;\n }\n\n if (baseUrl.endsWith(wellKnownPath)) {\n return baseUrl;\n }\n\n return `${baseUrl.replace(/\\/+$/, '')}${wellKnownPath}`;\n })();\n\n const cache = (() => {\n if (options.cache) return options.cache;\n let memoryValue: JWKS | undefined;\n return {\n get: () => memoryValue,\n set: (_key: string, value: JWKS) => {\n memoryValue = value;\n }\n };\n })();\n\n let cachedJWKS: JWKS | undefined;\n let nextRefreshAt = 0;\n let refreshInFlight: Promise<JWKS> | undefined;\n let consecutiveFailures = 0;\n\n const fetchJWKS = async (allowStaleOnFailure: boolean): Promise<JWKS> => {\n if (refreshInFlight) return refreshInFlight;\n\n refreshInFlight = (async () => {\n const controller = new AbortController();\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n\n if (timeoutMs > 0) {\n timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);\n }\n\n let response: Response;\n try {\n response = await fetchFn(endpoint, {signal: controller.signal});\n } catch (error) {\n if (controller.signal.aborted) {\n throw new Error(`JWKS fetch timed out after ${timeoutMs}ms`);\n }\n throw error;\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n\n if (!response.ok) {\n throw new Error(`Failed to fetch JWKS: ${response.status} ${response.statusText}`);\n }\n\n const body = await response.json();\n if (!body || typeof body !== 'object' || !Array.isArray((body as any).keys)) {\n throw new Error('Invalid JWKS');\n }\n\n return normalizeJWKS(body as JWKS);\n })();\n\n try {\n const fresh = await refreshInFlight;\n cachedJWKS = fresh;\n await cache.set(endpoint, fresh);\n consecutiveFailures = 0;\n if (ttl > 0) nextRefreshAt = Date.now() + ttl;\n return fresh;\n } catch (error) {\n if (!allowStaleOnFailure || !cachedJWKS) {\n throw error;\n }\n\n consecutiveFailures += 1;\n /* c8 ignore start - stale-on-failure is only reachable when ttl > 0 (auto-refresh path) */\n if (ttl > 0) {\n const backoff = Math.min(\n Math.max(ttl, 30_000) * Math.pow(2, consecutiveFailures - 1),\n 15 * 60_000\n );\n nextRefreshAt = Date.now() + backoff;\n }\n /* c8 ignore stop */\n console.warn(`JWKS refresh failed for \"${endpoint}\", using stale cache.`, error);\n return cachedJWKS;\n } finally {\n refreshInFlight = undefined;\n }\n };\n\n cachedJWKS = await cache.get(endpoint);\n if (!cachedJWKS) {\n cachedJWKS = await fetchJWKS(false);\n } else {\n cachedJWKS = normalizeJWKS(cachedJWKS);\n if (ttl > 0) nextRefreshAt = Date.now() + ttl;\n }\n\n\n const resolver: JWKSResolver = {\n async list(): Promise<JWKWithHelpers[]> {\n if (ttl > 0 && Date.now() >= nextRefreshAt) {\n await fetchJWKS(true);\n }\n return normalizeJWK(...(cachedJWKS as JWKS).keys);\n },\n async refresh(): Promise<JWKSResolver> {\n await fetchJWKS(false);\n return resolver;\n },\n async key(kid: string): Promise<JWKWithHelpers | undefined> {\n const keys = await resolver.list();\n const key = keys.find((v) => v.kid === kid)\n if (!key) return undefined;\n return normalizeJWK(key)[0];\n },\n async find(input: Partial<BaseJWK>): Promise<JWKWithHelpers[]> {\n const keys = await resolver.list();\n const entries = Object.entries(input) as Array<[keyof BaseJWK, BaseJWK[keyof BaseJWK]]>;\n\n if (entries.length === 0) return normalizeJWK(...keys);\n\n return normalizeJWK(...keys.filter((key) =>\n entries.every(([field, expected]) => {\n const value = key[field];\n if (Array.isArray(expected)) {\n return Array.isArray(value)\n && value.length === expected.length\n && value.every((item, i) => item === expected[i]);\n }\n return value === expected;\n })\n ));\n },\n async findFirst(input: Partial<BaseJWK>): Promise<JWKWithHelpers | undefined> {\n return resolver.find(input).then(([key]) => key);\n },\n export(): JWKS | undefined {\n return cachedJWKS;\n }\n };\n\n return resolver;\n}\n\nexport const JWKS = {\n toKeyObject: JWKSToKeyObject,\n normalize: normalizeJWKS,\n fromWeb\n}\n"],"mappings":"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"}
|