UNPKG

@interopio/gateway

Version:

[![npm version](https://img.shields.io/npm/v/@interopio/gateway.svg)](https://www.npmjs.com/package/@interopio/gateway)

3 lines (2 loc) 6.7 kB
async function g(r,t,e){let s=await(e?.fetch??globalThis.fetch??fetch)(r.href,{signal:AbortSignal.timeout(t),headers:e?.headers});if(s.status!==200)throw new Error(`Failed to fetch ${r.href}: ${s.statusText}`);try{return await s.json()}catch{throw new Error("Failed to parse response")}}var x="/.well-known/openid-configuration",v="/.well-known/oauth-authorization-server";function W(r){if(!r.issuer)throw new Error("'issuer' not found is authorization server metadata")}async function $(r){let t=r.URL??globalThis.URL??URL,e=new t(r.issuerBaseUri);if(e.pathname.includes("/.well-known/")){let o=await g(e,r.timeout,r);return W(o),o}let s=[];e.pathname.endsWith("/")?s.push(`${e.pathname}${x.substring(1)}`):s.push(`${e.pathname}${x}`),e.pathname.endsWith("/")?s.push(`${v}`):s.push(`${v}${e.pathname}`);for(let o of s)try{let a=new t(o,e),i=await g(a,r.timeout,r);return W(i),i}catch{}throw new Error("Failed to fetch authorization server metadata")}var V=r=>{let t,e=0;return()=>{let s=Date.now();return(!t||s>e+r.cacheMaxAge)&&(e=s,t=$(r).catch(o=>{throw t=void 0,o})),t}};import{KEYUTIL as G,RSAKey as Y}from"jsrsasign";var c=class extends Error{static code="ERR_JOSE_GENERIC";code="ERR_JOSE_GENERIC";constructor(t,e){super(t,e),this.name=this.constructor.name,Error.captureStackTrace(this,this.constructor)}},h=class extends c{static code="ERR_JOSE_NOT_SUPPORTED";code="ERR_JOSE_NOT_SUPPORTED"},y=class extends c{static code="ERR_JWS_INVALID";code="ERR_JWS_INVALID"},l=class extends c{static code="ERR_JWKS_INVALID";code="ERR_JWKS_INVALID"},w=class extends c{static code="ERR_JWKS_NO_MATCHING_KEY";code="ERR_JWKS_NO_MATCHING_KEY";constructor(t="No matching key found in the JSON Web Key Set",e){super(t,e)}},m=class extends c{static code="ERR_JWKS_TIMEOUT";code="ERR_JWKS_TIMEOUT";constructor(t="request timed out",e){super(t,e)}};function q(r){switch(typeof r=="string"&&r.slice(0,2)){case"RS":case"PS":return"RSA";case"ES":return"EC";case"Ed":return"OKP";default:throw new h('Unsupported "alg" value for a JSON Web Key Set')}}function z(r){return!!r&&typeof r=="object"&&Array.isArray(r.keys)}var R=class{#e;#t=new WeakMap;constructor(t){if(!z(t))throw new l("JSON Web Key Set malformed");this.#e=structuredClone(t)}jwks(){return this.#e}async getKey(t,e){let{alg:s,kid:o}={...t,...e?.header},a=q(s),i=this.#e.keys.filter(u=>{let d=u.kty===a;return d&&typeof o=="string"&&(d=u.kid===o),d&&typeof u.alg=="string"&&(d=u.alg===s),d&&typeof u.use=="string"&&(d=u.use==="sig"),d}),{0:n,length:f}=i;if(f===0)throw new w;if(f!==1)throw new Error("Multiple matching keys found");return B(this.#t,n,s)}};async function B(r,t,e){let s=r.get(t)||r.set(t,{}).get(t);if(s[e]===void 0){let o=G.getKey(t);if(o instanceof Y)s[e]=o;else throw new Error("RSA key expected!")}return s[e]}function I(r){let t=new R(r),e=async(s,o)=>await t.getKey(s,o);return Object.defineProperties(e,{jwks:{value:()=>structuredClone(t.jwks()),enumerable:!1,configurable:!1,writable:!1}}),e}async function Q(r,t,e,s){let o=await(s?.fetch??globalThis.fetch??fetch)(r,{method:"GET",signal:e,redirect:"manual",headers:t}).catch(a=>{throw a.name==="TimeoutError"?new m:a});if(o.status!==200)throw new c(`Expected 200 OK from JSON Web Key Set response, got ${o.status} ${o.statusText}`);try{return await o.json()}catch(a){throw new c(`Failed to parse the JSON Web Key Set response as JSON: ${a instanceof Error?a.message:String(a)}`)}}var S=class{#e;#t;#n;#a;#o;#r;#i;#s;constructor(t,e){this.#e=e.fetch,this.#t=new(e.URL??globalThis.URL??URL)(t.href),this.#i=new(e.Headers??globalThis.Headers??Headers)(e.headers),this.#n=typeof e.timeout=="number"?e.timeout:5e3,this.#a=typeof e.cacheMaxAge=="number"?e.cacheMaxAge:6e5}fresh(){return typeof this.#o=="number"?Date.now()<this.#o+this.#a:!1}jwks(){return this.#s?.jwks()}async getKey(t,e){return(!this.#s||!this.fresh())&&await this.reload(),await this.#s(t,e)}async reload(){this.#r||=Q(this.#t.href,this.#i,AbortSignal.timeout(this.#n),{fetch:this.#e}).then(t=>{this.#s=I(t),this.#o=Date.now(),this.#r=void 0}).catch(t=>{throw this.#r=void 0,t}),await this.#r}};function U(r,t){let e=new S(r,t),s=async(o,a)=>e.getKey(o,a);return Object.defineProperties(s,{jwks:{value:()=>structuredClone(e.jwks()),enumerable:!1,configurable:!1,writable:!1}}),s}var T=r=>{let t=r.URL??URL,e,s;return o=>((e===void 0||s!==o)&&(s=o,e=U(new t(o),r)),e)};import{KJUR as b}from"jsrsasign";function K(r){if(typeof r=="string")return[r];if(Array.isArray(r))return r}function H(r,t,e){let{headerObj:s,payloadObj:o}=b.jws.JWS.parse(r),a={alg:e?.algorithms??[s.alg],aud:K(e?.audience),iss:K(e?.issuer),sub:K(e?.subject),gracePeriod:e?.clockTolerance};if(typeof t=="function")return t(s).then(i=>b.jws.JWS.verifyJWT(r,i,a)).then(i=>{if(!i)throw new y;return{payload:o,protectedHeader:s}});if(b.jws.JWS.verifyJWT(r,t,a))return{payload:o,protectedHeader:s};throw new y}var A=(r,t,e)=>{for(let[s,o]of Object.entries(e))if(o!==!1){let a=s==="alg"||s==="typ"?t[s]:r[s];if(!(typeof o=="string"&&a===o||typeof o=="function"&&o(a,r,t)))throw new Error(`Unexpected '${s}' value: ${JSON.stringify(a)}`)}},M=(r,t,e,s,o,a,i)=>({alg:n=>typeof n=="string"&&n.toLowerCase()!=="none"&&(a===void 0||a.includes(n))&&(i===void 0||n===i),typ:n=>!o||typeof n=="string"&&n.toLowerCase().replace(/^application\//,"")==="at+jwt",iss:n=>typeof n=="string"&&n===r,aud:n=>(t=typeof t=="string"?[t]:t,typeof n=="string"?t.includes(n):Array.isArray(n)?t.some(Set.prototype.has.bind(new Set(n))):!1),exp:n=>{let f=Math.floor(Date.now()/1e3);return typeof n=="number"&&n>=f-e},iat:n=>{if(s===void 0)return n===void 0&&!o||typeof n=="number";let f=Math.floor(Date.now()/1e3);return typeof n=="number"&&n<f+e&&n>f-e-s},sub:n=>n===void 0&&!o||typeof n=="string",jti:n=>n===void 0&&!o||typeof n=="string"});var J=class extends Error{},X=({issuerBaseUri:r="",jwksUri:t="",issuer:e="",audience:s="",tokenSigningAlg:o,timeout:a=5e3,cacheMaxAge:i=6e5,clockTolerance:n=5,maxTokenAge:f,strict:u=!1,validators:d,fetch:k,URL:E})=>{let O,P;if(!(r||e&&t))throw new Error("Either 'issuerBaseUri' or both 'issuer' and 'jwksUri' must be provided");if(!s)throw new Error("An 'audience' is required to validate the 'aud' claim");let C=V({issuerBaseUri:r,timeout:a,cacheMaxAge:i,fetch:k,URL:E}),j=T({timeout:a,cacheMaxAge:i,fetch:k,URL:E});return async L=>{try{if(r){let{jwks_uri:N,issuer:F,id_token_signing_alg_values_supported:D}=await C();t=t||N,e=e||F,O=D}P??={...M(e,s,n,f,u,O,o),...d};let{payload:p,protectedHeader:_}=await H(L,j(t),{clockTolerance:n});return A(p,_,P),{payload:p,header:_,token:L}}catch(p){throw new J(`${p instanceof Error?p.message:String(p)}`)}}},Z=X;export{J as JwtVerifyError,Z as jwtVerifier}; //# sourceMappingURL=jwt.js.map