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