@muze-nl/metro-oidc 0.1.3 → 0.2.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/dist/browser.js +2240 -1
- package/dist/browser.js.map +4 -4
- package/dist/browser.min.js +2 -0
- package/dist/browser.min.js.map +7 -0
- package/package.json +6 -6
- package/src/browser.mjs +5 -5
- package/src/oidcmw.mjs +44 -7
- package/dist/browser-dev.js +0 -1630
- package/dist/browser-dev.js.map +0 -7
package/dist/browser.js
CHANGED
|
@@ -1,2 +1,2241 @@
|
|
|
1
|
-
(()=>{var de=Object.defineProperty;var he=(e,n)=>{for(var t in n)de(e,t,{get:n[t],enumerable:!0})};var X={};he(X,{client:()=>me,formdata:()=>ie,metroError:()=>k,request:()=>K,response:()=>G,trace:()=>pe,url:()=>W});var B="https://metro.muze.nl/details/";Symbol.metroProxy||(Symbol.metroProxy=Symbol("isProxy"));Symbol.metroSource||(Symbol.metroSource=Symbol("source"));var E=class e{#e={url:typeof window<"u"?window.location:"https://localhost"};#t=["get","post","put","delete","patch","head","options","query"];static tracers={};constructor(...n){for(let t of n)if(typeof t=="string"||t instanceof String)this.#e.url=""+t;else if(t instanceof e)Object.assign(this.#e,t.#e);else if(t instanceof Function)this.#r([t]);else if(t&&typeof t=="object")for(let r in t)r=="middlewares"?this.#r(t[r]):typeof t[r]=="function"?this.#e[r]=t[r](this.#e[r],this.#e):this.#e[r]=t[r];this.#e.verbs&&(this.#t=this.#e.verbs,delete this.#e.verbs);for(let t of this.#t)this[t]=async function(...r){return this.fetch(K(this.#e,...r,{method:t.toUpperCase()}))};Object.freeze(this)}#r(n){typeof n=="function"&&(n=[n]);let t=n.findIndex(r=>typeof r!="function");if(t>=0)throw k("metro.client: middlewares must be a function or an array of functions "+B+"client/invalid-middlewares-value/",n[t]);Array.isArray(this.#e.middlewares)||(this.#e.middlewares=[]),this.#e.middlewares=this.#e.middlewares.concat(n)}fetch(n,t){if(n=K(n,t),!n.url)throw k("metro.client."+n.method.toLowerCase()+": Missing url parameter "+B+"client/missing-url-param/",n);if(t||(t={}),typeof t!="object"||Array.isArray(t)||t instanceof String)throw k("metro.client.fetch: Options is not an object");let o=[async function(f){if(f[Symbol.metroProxy])if(f.body&&f.body[Symbol.metroSource]){let O=f.body[Symbol.metroSource];f=new Request(f[Symbol.metroSource],{body:O})}else f=f[Symbol.metroSource];let x=await fetch(f);return G(x)}].concat(this.#e?.middlewares?.slice()||[]);t=Object.assign({},this.#e,t);let i;for(let u of o)i=function(f,x){return async function(O){let T,D=Object.values(e.tracers);for(let a of D)a.request&&a.request.call(a,O,x);T=await x(O,f);for(let a of D)a.response&&a.response.call(a,T,x);return T}}(i,u);return i(n)}with(...n){return new e(this,...n)}};function me(...e){return new E(...e)}function q(e,n){let t=n.body;return t||(e===null?t=new ReadableStream:e instanceof ReadableStream?t=e:e instanceof Blob?t=e.stream():t=new ReadableStream({start(r){let o;switch(typeof e){case"object":if(typeof e.toString=="function")o=e.toString();else if(e instanceof FormData)o=new URLSearchParams(e).toString();else if(e instanceof ArrayBuffer||ArrayBuffer.isView(e))o=e;else throw k("Cannot convert body to ReadableStream",e);break;case"string":case"number":case"boolean":o=e;break;default:throw k("Cannot convert body to ReadableStream",e)}r.enqueue(o),r.close()}})),new Proxy(t,{get(r,o,i){switch(o){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"toString":return function(){return""+e}}if(e&&typeof e=="object"&&o in e)return typeof e[o]=="function"?function(...u){return e[o].apply(e,u)}:e[o];if(o in r&&o!="toString")return typeof r[o]=="function"?function(...u){return r[o].apply(r,u)}:r[o]},has(r,o){return e&&typeof e=="object"?o in e:o in r},ownKeys(r){return Reflect.ownKeys(e&&typeof e=="object"?e:r)},getOwnPropertyDescriptor(r,o){return Object.getOwnPropertyDescriptor(e&&typeof e=="object"?e:r,o)}})}function _e(e,n){let t=n||{};!t.url&&n.url&&(t.url=n.url);for(let r of["method","headers","body","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","priority","url"])if(typeof e[r]=="function")e[r](t[r],t);else if(typeof e[r]<"u")if(r=="url")t.url=W(t.url,e.url);else if(r=="headers"){t.headers=new Headers(n.headers),e.headers instanceof Headers||(e.headers=new Headers(e.headers));for(let[o,i]of e.headers.entries())t.headers.set(o,i)}else t[r]=e[r];return t}function K(...e){let n={url:typeof window<"u"?window.location:"https://localhost/",duplex:"half"};for(let o of e)typeof o=="string"||o instanceof URL||o instanceof URLSearchParams?n.url=W(n.url,o):o&&(o instanceof FormData||o instanceof ReadableStream||o instanceof Blob||o instanceof ArrayBuffer||o instanceof DataView)?n.body=o:o&&typeof o=="object"&&Object.assign(n,_e(o,n));let t=n.body;t&&typeof t=="object"&&!(t instanceof String)&&!(t instanceof ReadableStream)&&!(t instanceof Blob)&&!(t instanceof ArrayBuffer)&&!(t instanceof DataView)&&!(t instanceof FormData)&&!(t instanceof URLSearchParams)&&(typeof TypedArray>"u"||!(t instanceof TypedArray))&&(n.body=JSON.stringify(t));let r=new Request(n.url,n);return Object.freeze(r),new Proxy(r,{get(o,i,u){switch(i){case Symbol.metroSource:return o;case Symbol.metroProxy:return!0;case"with":return function(...f){return t&&f.unshift({body:t}),K(o,...f)};case"body":if(t||(t=o.body),t)return t[Symbol.metroProxy]?t:q(t,o);break}return o[i]instanceof Function?o[i].bind(o):o[i]}})}function ne(e,n){let t=n||{};!t.url&&n.url&&(t.url=n.url);for(let r of["status","statusText","headers","body","url","type","redirected"])typeof e[r]=="function"?e[r](t[r],t):typeof e[r]<"u"&&(r=="url"?t.url=new URL(e.url,t.url||"https://localhost/"):t[r]=e[r]);return t}function G(...e){let n={};for(let r of e)typeof r=="string"?n.body=r:r instanceof Response?Object.assign(n,ne(r,n)):r&&typeof r=="object"&&(r instanceof FormData||r instanceof Blob||r instanceof ArrayBuffer||r instanceof DataView||r instanceof ReadableStream||r instanceof URLSearchParams||r instanceof String||typeof TypedArray<"u"&&r instanceof TypedArray?n.body=r:Object.assign(n,ne(r,n)));let t=new Response(n.body,n);return Object.freeze(t),new Proxy(t,{get(r,o,i){switch(o){case Symbol.metroProxy:return!0;case Symbol.metroSource:return r;case"with":return function(...u){return G(r,...u)};case"body":return n.body?n.body[Symbol.metroProxy]?n.body:q(n.body,r):q("",r);case"ok":return r.status>=200&&r.status<400;case"headers":return r.headers;default:if(o in n&&o!="toString")return n[o];if(o in r&&o!="toString")return typeof r[o]=="function"?function(...u){return r[o].apply(r,u)}:r[o];break}}})}function oe(e,n){typeof n=="function"?n(e.searchParams,e):(n=new URLSearchParams(n),n.forEach((t,r)=>{e.searchParams.append(r,t)}))}function W(...e){let n=["hash","host","hostname","href","password","pathname","port","protocol","username","search","searchParams"],t=new URL("https://localhost/");for(let r of e)if(typeof r=="string"||r instanceof String)t=new URL(r,t);else if(r instanceof URL||typeof Location<"u"&&r instanceof Location)t=new URL(r);else if(r instanceof URLSearchParams)oe(t,r);else if(r&&typeof r=="object")for(let o in r)if(o=="search")typeof r.search=="function"?r.search(t.search,t):t.search=new URLSearchParams(r.search);else if(o=="searchParams")oe(t,r.searchParams);else{if(!n.includes(o))throw k("metro.url: unknown url parameter "+B+"url/unknown-param-name/",o);if(typeof r[o]=="function")r[o](t[o],t);else if(typeof r[o]=="string"||r[o]instanceof String||typeof r[o]=="number"||r[o]instanceof Number||typeof r[o]=="boolean"||r[o]instanceof Boolean)t[o]=""+r[o];else if(typeof r[o]=="object"&&r[o].toString)t[o]=r[o].toString();else throw k("metro.url: unsupported value for "+o+" "+B+"url/unsupported-param-value/",e[o])}else throw k("metro.url: unsupported option value "+B+"url/unsupported-option-value/",r);return Object.freeze(t),new Proxy(t,{get(r,o,i){switch(o){case Symbol.metroProxy:return!0;case Symbol.metroSource:return r;case"with":return function(...u){return W(r,...u)}}return r[o]instanceof Function?r[o].bind(r):r[o]}})}function ie(...e){var n=new FormData;for(let t of e)if(t instanceof FormData)for(let r of t.entries())n.append(r[0],r[1]);else if(t&&typeof t=="object")for(let r of Object.entries(t))if(Array.isArray(r[1]))for(let o of r[1])n.append(r[0],o);else n.append(r[0],r[1]);else throw new k("metro.formdata: unknown option type, only FormData or Object supported",t);return Object.freeze(n),new Proxy(n,{get:(t,r,o)=>{switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return t;case"with":return function(...i){return ie(t,...i)}}return t[r]instanceof Function?t[r].bind(t):t[r]}})}var M={error:(e,...n)=>{console.error("\u24C2\uFE0F ",e,...n)},info:(e,...n)=>{console.info("\u24C2\uFE0F ",e,...n)},group:e=>{console.group("\u24C2\uFE0F "+e)},groupEnd:e=>{console.groupEnd("\u24C2\uFE0F "+e)}};function k(e,...n){return M.error(e,...n),new Error(e,...n)}var pe={add(e,n){E.tracers[e]=n},delete(e){delete E.tracers[e]},clear(){E.tracers={}},group(){let e=0;return{request:(n,t)=>{e++,M.group(e),M.info(n?.url,n,t)},response:(n,t)=>{M.info(n?.body?n.body[Symbol.metroSource]:null,n,t),M.groupEnd(e),e--}}}};function j(e){return e=Object.assign({reviver:null,replacer:null,space:""},e),async(n,t)=>{["POST","PUT","PATCH","QUERY"].includes(n.method)?(n=n.with({headers:{"Content-Type":"application/json",Accept:"application/json"}}),n.body&&typeof n.body[Symbol.metroSource]=="object"&&(n=n.with({body:JSON.stringify(n.body[Symbol.metroSource],e.replacer,e.space)}))):n=n.with({headers:{Accept:"application/json"}});let r=await t(n),o=await r.text(),i=JSON.parse(o,e.reviver);return r.with({body:i})}}function A(e){return async(n,t)=>{let r=await t(n);if(!r.ok)if(e&&typeof e[r.status]=="function")r=e[r.status].apply(r,n);else throw new Error(r.status+": "+r.statusText,{cause:r});return r}}var se=Object.assign({},X,{mw:{jsonmw:j,thrower:A}});window.metro=se;var d=se;globalThis.assertEnabled=!1;function v(e,n){if(globalThis.assertEnabled){let t=g(e,n);if(t)throw console.error("\u{1F170}\uFE0F Assertions failed because of:",t,"in this source:",e),new Error("Assertions failed",{cause:{problems:t,source:e}})}}function s(e){return function(t,r,o){if(typeof t<"u"&&t!=null&&typeof e<"u")return g(t,e,r,o)}}function _(e){return function(t,r,o){return t==null||typeof t>"u"?m("data is required",t,e||"any value",o):typeof e<"u"?g(t,e,r,o):!1}}function C(e){return function(t,r,o){return t==null||typeof t>"u"?(console.warn("data does not contain recommended value",t,e,o),!1):g(t,e,r,o)}}function y(...e){return function(t,r,o){for(let i of e)if(!g(t,i,r,o))return!1;return m("data does not match oneOf patterns",t,e,o)}}function U(...e){return function(t,r,o){if(!Array.isArray(t))return m("data is not an array",t,"anyOf",o);for(let i of t)if(y(...e)(i))return m("data does not match anyOf patterns",i,e,o);return!1}}function ae(...e){return function(t,r,o){let i=[];for(let u of e)i=i.concat(g(t,u,r,o));if(i=i.filter(Boolean),i.length)return m("data does not match all given patterns",t,e,o,i)}}function h(e,n,t){try{e instanceof URL&&(e=e.href);let r=new URL(e);if(r.href!=e&&!(r.href+"/"==e||r.href==e+"/"))return m("data is not a valid url",e,"validURL",t)}catch{return m("data is not a valid url",e,"validURL",t)}}function ce(e,n,t){if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return m("data is not a valid email",e,"validEmail",t)}function z(e){return function(t,r,o){if(!(t instanceof e))return m("data is not an instanceof pattern",t,e,o)}}function F(e){return function(t,r,o){if(!g(t,e,r,o))return m("data matches pattern, when required not to",t,e,o)}}function g(e,n,t,r=""){t||(t=e);let o=[];if(n===Boolean)typeof e!="boolean"&&!(e instanceof Boolean)&&o.push(m("data is not a boolean",e,n,r));else if(n===Number)typeof e!="number"&&!(e instanceof Number)&&o.push(m("data is not a number",e,n,r));else if(n===String)typeof e!="string"&&!(e instanceof String)&&o.push(m("data is not a string",e,n,r)),e==""&&o.push(m("data is an empty string, which is not allowed",e,n,r));else if(n instanceof RegExp)if(Array.isArray(e)){let i=e.findIndex((u,f)=>g(u,n,t,r+"["+f+"]"));i>-1&&o.push(m("data["+i+"] does not match pattern",e[i],n,r+"["+i+"]"))}else typeof e>"u"?o.push(m("data is undefined, should match pattern",e,n,r)):n.test(e)||o.push(m("data does not match pattern",e,n,r));else if(n instanceof Function){let i=n(e,t,r);i&&(Array.isArray(i)?o=o.concat(i):o.push(i))}else if(Array.isArray(n)){Array.isArray(e)||o.push(m("data is not an array",e,[],r));for(let i of n)for(let u of e.keys()){let f=g(e[u],i,t,r+"["+u+"]");Array.isArray(f)?o=o.concat(f):f&&o.push(f)}}else if(n&&typeof n=="object")if(Array.isArray(e)){let i=e.findIndex((u,f)=>g(u,n,t,r+"["+f+"]"));i>-1&&o.push(m("data["+i+"] does not match pattern",e[i],n,r+"["+i+"]"))}else if(!e||typeof e!="object")o.push(m("data is not an object, pattern is",e,n,r));else if(e instanceof URLSearchParams&&(e=Object.fromEntries(e)),n instanceof Function){let i=g(e,n,t,r);i&&(o=o.concat(i))}else for(let[i,u]of Object.entries(n)){let f=g(e[i],u,t,r+"."+i);f&&(o=o.concat(f))}else n!=e&&o.push(m("data and pattern are not equal",e,n,r));return o.length?o:!1}function m(e,n,t,r,o){let i={message:e,found:n,expected:t,path:r};return o&&(i.problems=o),i}var I=(...e)=>(n,t)=>e.filter(r=>t.hasOwnKey(r)).length>0?!1:m("root data must have all of",t,e),R=(...e)=>n=>Array.isArray(n)&&e.filter(t=>!n.includes(t)).length==0?!1:m("data must be an array which includes",n,e);var S=["HS256","HS384","HS512","RS256","RS384","RS512","ES256","ES384","ES512"],$=["client_secret_post","client_secret_basic","client_secret_jwt","private_key_jwt"];async function H(e={}){v(e,{client:s(z(d.client().constructor)),issuer:_(h)});let n={client:d.client().with(A()).with(j()),requireDynamicRegistration:!1};e=Object.assign({},n,e);let t=!1;function r(x){return t}let o={issuer:_(ae(e.issuer,r)),authorization_endpoint:_(h),token_endpoint:_(h),userinfo_endpoint:C(h),jwks_uri:_(h),registration_endpoint:e.requireDynamicRegistration?_(h):C(h),scopes_supported:C(R("openid")),response_types_supported:e.requireDynamicRegistration?_(R("code","id_token","id_token token")):_([]),response_modes_supported:s([]),grant_types_supported:e.requireDynamicRegistration?s(R("authorization_code")):s([]),acr_values_supported:s([]),subject_types_supported:_([]),id_token_signing_alg_values_supported:_(R("RS256")),id_token_encryption_alg_values_supported:s([]),id_token_encryption_enc_values_supported:s([]),userinfo_signing_alg_values_supported:s([]),userinfo_encryption_alg_values_supported:s([]),userinfo_encryption_enc_values_supported:s([]),request_object_signing_alg_values_supported:s(R("RS256")),request_object_encryption_alg_values_supported:s([]),request_object_encryption_enc_values_supported:s([]),token_endpoint_auth_methods_supported:s(U(...$)),token_endpoint_auth_signing_alg_values_supported:s(R("RS256"),F(R("none"))),display_values_supported:s(U("page","popup","touch","wap")),claim_types_supported:s(U("normal","aggregated","distributed")),claims_supported:C([]),service_documentation:s(h),claims_locales_supported:s([]),ui_locales_supported:s([]),claims_parameter_supported:s(Boolean),request_parameter_supported:s(Boolean),request_uri_parameter_supported:s(Boolean),op_policy_uri:s(h),op_tos_uri:s(h)},i=d.url(e.issuer,".well-known/openid-configuration"),f=(await e.client.get(i)).body[Symbol.metroSource];return v(f,o),v(f.issuer,e.issuer),f}async function N(e){let n={redirect_uris:_([h]),response_types:s([]),grant_types:s(U("authorization_code","refresh_token")),application_type:s(y("native","web")),contacts:s([ce]),client_name:s(String),logo_uri:s(h),client_uri:s(h),policy_uri:s(h),tos_uri:s(h),jwks_uri:s(h,F(I("jwks"))),jwks:s(h,F(I("jwks_uri"))),sector_identifier_uri:s(h),subject_type:s(String),id_token_signed_response_alg:s(y(...S)),id_token_encrypted_response_alg:s(y(...S)),id_token_encrypted_response_enc:s(y(...S),I("id_token_encrypted_response_alg")),userinfo_signed_response_alg:s(y(...S)),userinfo_encrypted_response_alg:s(y(...S)),userinfo_encrypted_response_enc:s(y(...S),I("userinfo_encrypted_response_alg")),request_object_signing_alg:s(y(...S)),request_object_encryption_alg:s(y(...S)),request_object_encryption_enc:s(y(...S)),token_endpoint_auth_method:s(y(...$)),token_endpoint_auth_signing_alg:s(y(...S)),default_max_age:s(Number),require_auth_time:s(Boolean),default_acr_values:s([String]),initiate_login_uri:s([h]),request_uris:s([h])};v(e,{client:s(z(d.client().constructor)),registration_endpoint:h,client_info:n});let t={client:d.client().with(A()).with(j())};e=Object.assign({},t,e);let r=await e.client.post(e.registration_endpoint,{body:e.client_info}),o=r.body;if(!o.client_id||!o.client_secret)throw d.metroError("metro.oidc: Error: dynamic registration of client failed, no client_id or client_secret returned",r);return e.client_info=Object.assign(e.client_info,o),e.client_info}globalThis.assertEnabled=!1;var J=(e,n)=>{if(globalThis.assertEnabled){let t=L(e,n);if(t)throw new Z("Assertions failed",t,e)}};var V=e=>n=>L(n,e);function Q(e){try{if(e instanceof URL&&(e=e.href),new URL(e).href!=e)return w("data is not a valid url",e,"validURL")}catch{return w("data is not a valid url",e,"validURL")}return!1}function L(e,n,t){t||(t=e);let r=[];if(n===Boolean)typeof e!="boolean"&&r.push(w("data is not a boolean",e,n));else if(n===Number)typeof e!="number"&&r.push(w("data is not a number",e,n));else if(n instanceof RegExp)if(Array.isArray(e)){let o=e.findIndex(i=>L(i,n,t));o>-1&&r.push(w("data["+o+"] does not match pattern",e[o],n))}else n.test(e)||r.push(w("data does not match pattern",e,n));else if(n instanceof Function)n(e,t)&&r.push(w("data does not match function",e,n));else if(Array.isArray(n)){Array.isArray(e)||r.push(w("data is not an array",e,[]));for(p of n){let o=L(e,p,t);Array.isArray(o)?r.concat(o):o&&r.push(o)}}else if(n&&typeof n=="object")if(Array.isArray(e)){let o=e.findIndex(i=>L(i,n,t));o>-1&&r.push(w("data["+o+"] does not match pattern",e[o],n))}else if(!e||typeof e!="object")r.push(w("data is not an object, pattern is",e,n));else{e instanceof URLSearchParams&&(e=Object.fromEntries(e));let o=r[r.length-1];for(let[i,u]of Object.entries(n)){let f=L(e[i],u,t);f&&((!o||typeof o=="string")&&(o={},r.push(w(o,e[i],u))),o[i]=f.problems)}}else n!=e&&r.push(w("data and pattern are not equal",e,n));return r.length?r:!1}var Z=class extends Error{constructor(n,t,...r){super(n),this.problems=t,this.details=r}};function w(e,n,t){return{message:e,found:n,expected:t}}function fe(e){let n,t;if(typeof localStorage<"u")n={get:()=>localStorage.getItem("metro/state:"+e),set:r=>localStorage.setItem("metro/state:"+e,r),has:()=>localStorage.getItem("metro/state:"+e)!==null},t={get:r=>JSON.parse(localStorage.getItem(e+":"+r)),set:(r,o)=>localStorage.setItem(e+":"+r,JSON.stringify(o)),has:r=>localStorage.getItem(e+":"+r)!==null};else{let r=new Map;n={get:()=>r.get("metro/state:"+e),set:o=>r.set("metro/state:"+e,o),has:()=>r.has("metro/state:"+e)},t=new Map}return{state:n,tokens:t}}function ee(e){let n={client:d.client(),force_authorization:!1,site:"default",oauth2_configuration:{authorization_endpoint:"/authorize",token_endpoint:"/token",redirect_uri:globalThis.document?.location.href,grant_type:"authorization_code",code_verifier:Y.generateCodeVerifier(64)},callbacks:{authorize:async a=>(window.location.href!=a.href&&window.location.replace(a.href),!1)}};J(e,{});let t=Object.assign({},n.oauth2_configuration,e?.oauth2_configuration);e=Object.assign({},n,e),e.oauth2_configuration=t;let r=fe(e.site);e.tokens||(e.tokens=r.tokens),e.state||(e.state=r.state),J(e,{oauth2_configuration:{client_id:V(/.+/),grant_type:"authorization_code",authorization_endpoint:V(Q),token_endpoint:V(Q),redirect_uri:V(Q)}});for(let a in t)switch(a){case"access_token":case"authorization_code":case"refresh_token":e.tokens.set(a,t[a]);break}return async function(a,l){if(e.force_authorization)return o(a,l);let c;try{if(c=await l(a),c.ok)return c}catch(b){switch(c.status){case 400:case 401:return o(a,l)}throw b}return c};async function o(a,l){if(i(),e.tokens.has("access_token")){if(T(a))return await f()?o(a,l):d.response("false");{let c=e.tokens.get("access_token");return a=d.request(a,{headers:{Authorization:c.type+" "+c.value}}),l(a)}}else{try{if(!await u())return d.response("false")}catch(c){throw console.log("caught",c),c}return o(a,l)}}function i(){if(typeof window<"u"&&window?.location){let a=d.url(window.location),l,c,b;if(a.searchParams.has("code"))b=a.searchParams,a=a.with({search:""}),history.pushState({},"",a.href);else if(a.hash){let P=a.hash.substr(1);b=new URLSearchParams("?"+P),a=a.with({hash:""}),history.pushState({},"",a.href)}if(b){l=b.get("code"),c=b.get("state");let P=e.state.get("metro/state");if(!c||c!==P)return;l&&e.tokens.set("authorization_code",l)}}}async function u(){if(t.grant_type==="authorization_code"&&!e.tokens.has("authorization_code")){let b=x();if(!e.callbacks.authorize||typeof e.callbacks.authorize!="function")throw d.metroError("oauth2mw: oauth2 with grant_type:authorization_code requires a callback function in client options.options.callbacks.authorize");let P=await e.callbacks.authorize(b);if(P)e.tokens.set("authorization_code",P);else return!1}let a=O(),l=await e.client.post(a);if(!l.ok)throw d.metroError("OAuth2mw: fetch access_token: "+l.status+": "+l.statusText,{cause:a});let c=await l.json();if(e.tokens.set("access_token",{value:c.access_token,expires:D(c.expires_in),type:c.token_type,scope:c.scope}),c.refresh_token){let b={value:c.refresh_token};e.tokens.set("refresh_token",b)}return c}async function f(){let a=O("refresh_token"),l=await e.client.post(a);if(!l.ok)throw d.metroError("OAuth2mw: refresh access_token: "+l.status+": "+l.statusText,{cause:a});let c=await l.json();if(e.tokens.set("access_token",{value:c.access_token,expires:D(c.expires_in),type:c.token_type,scope:c.scope}),c.refresh_token){let b={value:c.refresh_token};e.tokens.set("refresh_token",b)}else return!1;return c}function x(){if(!t.authorization_endpoint)throw d.metroError("oauth2mw: Missing options.oauth2_configuration.authorization_endpoint");let a=d.url(t.authorization_endpoint,{hash:""});J(t,{client_id:/.+/,redirect_uri:/.+/,scope:/.*/});let l={response_type:"code",client_id:t.client_id,client_secret:t.client_secret,redirect_uri:t.redirect_uri,state:t.state||Y.createState(40)};return e.state.set(l.state),t.code_verifier&&(delete l.client_secret,l.code_challenge=Y.generateCodeChallenge(t.code_verifier),l.code_challenge_method="S256"),t.scope&&(l.scope=t.scope),d.url(a,{search:l})}function O(a=null){if(J(t,{client_id:/.+/,redirect_uri:/.+/}),!t.token_endpoint)throw d.metroError("oauth2mw: Missing options.endpoints.token url");let l=d.url(t.token_endpoint,{hash:""}),c={grant_type:a||t.grant_type,client_id:t.client_id};switch(t.code_verifier?c.code_verifier=t.code_verifier:c.client_secret=t.client_secret,t.scope&&(c.scope=t.scope),t.grant_type){case"authorization_code":c.redirect_uri=t.redirect_uri,c.code=e.tokens.get("authorization_code");break;case"client_credentials":break;case"refresh_token":c.refresh_token=t.refresh_token;break;default:throw new Error("Unknown grant_type: ".oauth2.grant_type)}return d.request(l,{method:"POST",body:new URLSearchParams(c)})}function T(a){if(a.oauth2&&a.options.tokens&&a.options.tokens.has("access_token")){let l=new Date,c=a.options.tokens.get("access_token");return l.getTime()>c.expires.getTime()}return!1}function D(a){if(a instanceof Date)return new Date(a.getTime());if(typeof a=="number"){let l=new Date;return l.setSeconds(l.getSeconds()+a),l}throw new TypeError("Unknown expires type "+a)}}var Y={generateCodeVerifier:function(e=64){let n=new Uint8Array(e);return globalThis.crypto.getRandomValues(n),n.toString("hex")},generateCodeChallenge:async function(e){let n=Y.base64url_encode(e),r=new TextEncoder().encode(n);return await globalThis.crypto.subtle.digest("SHA-256",r)},base64url_encode:function(e){let n=Array.from(new Uint8Array(e),t=>String.fromCharCode(t)).join("");return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},createState:function(e){let n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t="",r=0;for(;r<e;)t+=n.charAt(Math.floor(Math.random()*n.length)),r++;return t}};function le(){let e=new URL(document.location.href);if(!e.searchParams.has("code")){if(e.hash){let n=e.hash.substr(1);if(params=new URLSearchParams("?"+n),params.has("code"))return!0}return!1}return!0}function te(e){let n;if(typeof localStorage<"u")n={get:t=>JSON.parse(localStorage.getItem("metro/oidc:"+e+":"+t)),set:(t,r)=>localStorage.setItem("metro/oidc:"+e+":"+t,JSON.stringify(r)),has:t=>localStorage.getItem("metro/oidc:"+e+":"+t)!==null};else{let t=new Map;n={get:r=>JSON.parse(t.get("metro/oidc:"+e+":"+r)||null),set:(r,o)=>t.set("metro/oidc:"+e+":"+r,JSON.stringify(o)),has:r=>t.has("metro/oidc:"+e+":"+r)}}return n}function re(e={}){let n={client:d.client(),force_authorization:!1};return e=Object.assign({},n,e),v(e,{client:_(z(d.client().constructor)),client_info:_(),issuer:_(h),oauth2:s({}),openid_configuration:s()}),e.store||(e.store=te(e.issuer)),!e.openid_configuration&&e.store.has("openid_configuration")&&(e.openid_configuration=e.store.get("openid_configuration")),!e.client_info.client_id&&e.store.has("client_info")&&(e.client_info=e.store.get("client_info")),async(t,r)=>{let o;if(!e.force_authorization){try{o=await r(t)}catch(f){if(o.status!=401&&o.status!=403)throw f}if(o.ok||o.status!=401&&o.status!=403)return o}if(e.openid_configuration||(e.openid_configuration=await H({issuer:e.issuer}),e.store.set("openid_configuration",e.openid_configuration)),!e.client_info?.client_id){if(v(e.client_info?.client_name,_()),!e.openid_configuration.registration_endpoint)throw d.metroError("metro.oidcmw: Error: issuer "+e.issuer+" does not support dynamic client registration, but you haven't specified a client_id");e.client_info=await N({registration_endpoint:e.openid_configuration.registration_endpoint,client_info:e.client_info}),e.store.set("client_info",e.client_info)}let i=Object.assign({site:e.issuer,client:e.client,force_authorization:!0,oauth2_configuration:{client_id:e.client_info.client_id,client_secret:e.client_info.client_secret,code_verifier:!1,grant_type:"authorization_code",authorization_endpoint:e.openid_configuration.authorization_endpoint,token_endpoint:e.openid_configuration.token_endpoint,scope:e.openid_configuration.scope||"openid",redirect_uri:e.client_info.redirect_uris[0]}});return o=await e.client.with(e.issuer).with(ee(i)).fetch(t),o}}function ue(){return le()}var ye={discover:H,register:N,oidcmw:re,isRedirected:ue};globalThis.oidc=ye;})();
|
|
1
|
+
(() => {
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// node_modules/@muze-nl/metro/src/metro.mjs
|
|
9
|
+
var metro_exports = {};
|
|
10
|
+
__export(metro_exports, {
|
|
11
|
+
client: () => client,
|
|
12
|
+
formdata: () => formdata,
|
|
13
|
+
metroError: () => metroError,
|
|
14
|
+
request: () => request,
|
|
15
|
+
response: () => response,
|
|
16
|
+
trace: () => trace,
|
|
17
|
+
url: () => url
|
|
18
|
+
});
|
|
19
|
+
var metroURL = "https://metro.muze.nl/details/";
|
|
20
|
+
if (!Symbol.metroProxy) {
|
|
21
|
+
Symbol.metroProxy = Symbol("isProxy");
|
|
22
|
+
}
|
|
23
|
+
if (!Symbol.metroSource) {
|
|
24
|
+
Symbol.metroSource = Symbol("source");
|
|
25
|
+
}
|
|
26
|
+
var Client = class _Client {
|
|
27
|
+
#options = {
|
|
28
|
+
url: typeof window != "undefined" ? window.location : "https://localhost"
|
|
29
|
+
};
|
|
30
|
+
#verbs = ["get", "post", "put", "delete", "patch", "head", "options", "query"];
|
|
31
|
+
static tracers = {};
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} ClientOptions
|
|
34
|
+
* @property {Array} middlewares - list of middleware functions
|
|
35
|
+
* @property {string|URL} url - default url of the client
|
|
36
|
+
* @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']
|
|
37
|
+
*
|
|
38
|
+
* Constructs a new metro client. Can have any number of params.
|
|
39
|
+
* @params {ClientOptions|URL|Function|Client}
|
|
40
|
+
* @returns {Client} - A metro client object with given or default verb methods
|
|
41
|
+
*/
|
|
42
|
+
constructor(...options) {
|
|
43
|
+
for (let option of options) {
|
|
44
|
+
if (typeof option == "string" || option instanceof String) {
|
|
45
|
+
this.#options.url = "" + option;
|
|
46
|
+
} else if (option instanceof _Client) {
|
|
47
|
+
Object.assign(this.#options, option.#options);
|
|
48
|
+
} else if (option instanceof Function) {
|
|
49
|
+
this.#addMiddlewares([option]);
|
|
50
|
+
} else if (option && typeof option == "object") {
|
|
51
|
+
for (let param in option) {
|
|
52
|
+
if (param == "middlewares") {
|
|
53
|
+
this.#addMiddlewares(option[param]);
|
|
54
|
+
} else if (typeof option[param] == "function") {
|
|
55
|
+
this.#options[param] = option[param](this.#options[param], this.#options);
|
|
56
|
+
} else {
|
|
57
|
+
this.#options[param] = option[param];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (this.#options.verbs) {
|
|
63
|
+
this.#verbs = this.#options.verbs;
|
|
64
|
+
delete this.#options.verbs;
|
|
65
|
+
}
|
|
66
|
+
for (const verb of this.#verbs) {
|
|
67
|
+
this[verb] = async function(...options2) {
|
|
68
|
+
return this.fetch(request(
|
|
69
|
+
this.#options,
|
|
70
|
+
...options2,
|
|
71
|
+
{ method: verb.toUpperCase() }
|
|
72
|
+
));
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
Object.freeze(this);
|
|
76
|
+
}
|
|
77
|
+
#addMiddlewares(middlewares) {
|
|
78
|
+
if (typeof middlewares == "function") {
|
|
79
|
+
middlewares = [middlewares];
|
|
80
|
+
}
|
|
81
|
+
let index = middlewares.findIndex((m) => typeof m != "function");
|
|
82
|
+
if (index >= 0) {
|
|
83
|
+
throw metroError("metro.client: middlewares must be a function or an array of functions " + metroURL + "client/invalid-middlewares-value/", middlewares[index]);
|
|
84
|
+
}
|
|
85
|
+
if (!Array.isArray(this.#options.middlewares)) {
|
|
86
|
+
this.#options.middlewares = [];
|
|
87
|
+
}
|
|
88
|
+
this.#options.middlewares = this.#options.middlewares.concat(middlewares);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Mimics the standard browser fetch method, but uses any middleware installed through
|
|
92
|
+
* the constructor.
|
|
93
|
+
* @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request
|
|
94
|
+
* @param {Object} - Optional. Any object that is accepted by metro.request
|
|
95
|
+
* @return {Promise<Response|*>} - The metro.response to this request, or any other result as changed by any included middleware.
|
|
96
|
+
*/
|
|
97
|
+
fetch(req, options) {
|
|
98
|
+
req = request(req, options);
|
|
99
|
+
if (!req.url) {
|
|
100
|
+
throw metroError("metro.client." + req.method.toLowerCase() + ": Missing url parameter " + metroURL + "client/missing-url-param/", req);
|
|
101
|
+
}
|
|
102
|
+
if (!options) {
|
|
103
|
+
options = {};
|
|
104
|
+
}
|
|
105
|
+
if (!(typeof options === "object") || Array.isArray(options) || options instanceof String) {
|
|
106
|
+
throw metroError("metro.client.fetch: Options is not an object");
|
|
107
|
+
}
|
|
108
|
+
const metrofetch = async function browserFetch(req2) {
|
|
109
|
+
if (req2[Symbol.metroProxy]) {
|
|
110
|
+
if (req2.body && req2.body[Symbol.metroSource]) {
|
|
111
|
+
let body = req2.body[Symbol.metroSource];
|
|
112
|
+
req2 = new Request(req2[Symbol.metroSource], { body });
|
|
113
|
+
} else {
|
|
114
|
+
req2 = req2[Symbol.metroSource];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const res = await fetch(req2);
|
|
118
|
+
return response(res);
|
|
119
|
+
};
|
|
120
|
+
let middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || []);
|
|
121
|
+
options = Object.assign({}, this.#options, options);
|
|
122
|
+
let next;
|
|
123
|
+
for (let middleware of middlewares) {
|
|
124
|
+
next = /* @__PURE__ */ function(next2, middleware2) {
|
|
125
|
+
return async function(req2) {
|
|
126
|
+
let res;
|
|
127
|
+
let tracers = Object.values(_Client.tracers);
|
|
128
|
+
for (let tracer of tracers) {
|
|
129
|
+
if (tracer.request) {
|
|
130
|
+
tracer.request.call(tracer, req2, middleware2);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
res = await middleware2(req2, next2);
|
|
134
|
+
for (let tracer of tracers) {
|
|
135
|
+
if (tracer.response) {
|
|
136
|
+
tracer.response.call(tracer, res, middleware2);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return res;
|
|
140
|
+
};
|
|
141
|
+
}(next, middleware);
|
|
142
|
+
}
|
|
143
|
+
return next(req);
|
|
144
|
+
}
|
|
145
|
+
with(...options) {
|
|
146
|
+
return new _Client(this, ...options);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
function client(...options) {
|
|
150
|
+
return new Client(...options);
|
|
151
|
+
}
|
|
152
|
+
function bodyProxy(body, r) {
|
|
153
|
+
let source = r.body;
|
|
154
|
+
if (!source) {
|
|
155
|
+
if (body === null) {
|
|
156
|
+
source = new ReadableStream();
|
|
157
|
+
} else if (body instanceof ReadableStream) {
|
|
158
|
+
source = body;
|
|
159
|
+
} else if (body instanceof Blob) {
|
|
160
|
+
source = body.stream();
|
|
161
|
+
} else {
|
|
162
|
+
source = new ReadableStream({
|
|
163
|
+
start(controller) {
|
|
164
|
+
let chunk;
|
|
165
|
+
switch (typeof body) {
|
|
166
|
+
case "object":
|
|
167
|
+
if (typeof body.toString == "function") {
|
|
168
|
+
chunk = body.toString();
|
|
169
|
+
} else if (body instanceof FormData) {
|
|
170
|
+
chunk = new URLSearchParams(body).toString();
|
|
171
|
+
} else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
|
|
172
|
+
chunk = body;
|
|
173
|
+
} else {
|
|
174
|
+
throw metroError("Cannot convert body to ReadableStream", body);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
case "string":
|
|
178
|
+
case "number":
|
|
179
|
+
case "boolean":
|
|
180
|
+
chunk = body;
|
|
181
|
+
break;
|
|
182
|
+
default:
|
|
183
|
+
throw metroError("Cannot convert body to ReadableStream", body);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
controller.enqueue(chunk);
|
|
187
|
+
controller.close();
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return new Proxy(source, {
|
|
193
|
+
get(target, prop, receiver) {
|
|
194
|
+
switch (prop) {
|
|
195
|
+
case Symbol.metroProxy:
|
|
196
|
+
return true;
|
|
197
|
+
break;
|
|
198
|
+
case Symbol.metroSource:
|
|
199
|
+
return body;
|
|
200
|
+
break;
|
|
201
|
+
case "toString":
|
|
202
|
+
return function() {
|
|
203
|
+
return "" + body;
|
|
204
|
+
};
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
if (body && typeof body == "object") {
|
|
208
|
+
if (prop in body) {
|
|
209
|
+
if (typeof body[prop] == "function") {
|
|
210
|
+
return function(...args) {
|
|
211
|
+
return body[prop].apply(body, args);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return body[prop];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (prop in target && prop != "toString") {
|
|
218
|
+
if (typeof target[prop] == "function") {
|
|
219
|
+
return function(...args) {
|
|
220
|
+
return target[prop].apply(target, args);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return target[prop];
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
has(target, prop) {
|
|
227
|
+
if (body && typeof body == "object") {
|
|
228
|
+
return prop in body;
|
|
229
|
+
} else {
|
|
230
|
+
return prop in target;
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
ownKeys(target) {
|
|
234
|
+
if (body && typeof body == "object") {
|
|
235
|
+
return Reflect.ownKeys(body);
|
|
236
|
+
} else {
|
|
237
|
+
return Reflect.ownKeys(target);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
241
|
+
if (body && typeof body == "object") {
|
|
242
|
+
return Object.getOwnPropertyDescriptor(body, prop);
|
|
243
|
+
} else {
|
|
244
|
+
return Object.getOwnPropertyDescriptor(target, prop);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
function getRequestParams(req, current) {
|
|
250
|
+
let params2 = current || {};
|
|
251
|
+
if (!params2.url && current.url) {
|
|
252
|
+
params2.url = current.url;
|
|
253
|
+
}
|
|
254
|
+
for (let prop of [
|
|
255
|
+
"method",
|
|
256
|
+
"headers",
|
|
257
|
+
"body",
|
|
258
|
+
"mode",
|
|
259
|
+
"credentials",
|
|
260
|
+
"cache",
|
|
261
|
+
"redirect",
|
|
262
|
+
"referrer",
|
|
263
|
+
"referrerPolicy",
|
|
264
|
+
"integrity",
|
|
265
|
+
"keepalive",
|
|
266
|
+
"signal",
|
|
267
|
+
"priority",
|
|
268
|
+
"url"
|
|
269
|
+
]) {
|
|
270
|
+
let value = req[prop];
|
|
271
|
+
if (typeof value == "undefined" || value == null) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (value?.[Symbol.metroProxy]) {
|
|
275
|
+
value = value[Symbol.metroSource];
|
|
276
|
+
}
|
|
277
|
+
if (typeof value == "function") {
|
|
278
|
+
value(params2[prop], params2);
|
|
279
|
+
} else {
|
|
280
|
+
if (prop == "url") {
|
|
281
|
+
params2.url = url(params2.url, value);
|
|
282
|
+
} else if (prop == "headers") {
|
|
283
|
+
params2.headers = new Headers(current.headers);
|
|
284
|
+
if (!(value instanceof Headers)) {
|
|
285
|
+
value = new Headers(req.headers);
|
|
286
|
+
}
|
|
287
|
+
for (let [key, val] of value.entries()) {
|
|
288
|
+
params2.headers.set(key, val);
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
params2[prop] = value;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return params2;
|
|
296
|
+
}
|
|
297
|
+
function request(...options) {
|
|
298
|
+
let requestParams = {
|
|
299
|
+
url: typeof window != "undefined" ? window.location : "https://localhost/",
|
|
300
|
+
duplex: "half"
|
|
301
|
+
// required when setting body to ReadableStream, just set it here by default already
|
|
302
|
+
};
|
|
303
|
+
for (let option of options) {
|
|
304
|
+
if (typeof option == "string" || option instanceof URL || option instanceof URLSearchParams) {
|
|
305
|
+
requestParams.url = url(requestParams.url, option);
|
|
306
|
+
} else if (option && (option instanceof FormData || option instanceof ReadableStream || option instanceof Blob || option instanceof ArrayBuffer || option instanceof DataView)) {
|
|
307
|
+
requestParams.body = option;
|
|
308
|
+
} else if (option && typeof option == "object") {
|
|
309
|
+
Object.assign(requestParams, getRequestParams(option, requestParams));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
let body = requestParams.body;
|
|
313
|
+
if (body) {
|
|
314
|
+
if (typeof body == "object" && !(body instanceof String) && !(body instanceof ReadableStream) && !(body instanceof Blob) && !(body instanceof ArrayBuffer) && !(body instanceof DataView) && !(body instanceof FormData) && !(body instanceof URLSearchParams) && (typeof TypedArray == "undefined" || !(body instanceof TypedArray))) {
|
|
315
|
+
requestParams.body = JSON.stringify(body);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
let r = new Request(requestParams.url, requestParams);
|
|
319
|
+
Object.freeze(r);
|
|
320
|
+
return new Proxy(r, {
|
|
321
|
+
get(target, prop, receiver) {
|
|
322
|
+
switch (prop) {
|
|
323
|
+
case Symbol.metroSource:
|
|
324
|
+
return target;
|
|
325
|
+
break;
|
|
326
|
+
case Symbol.metroProxy:
|
|
327
|
+
return true;
|
|
328
|
+
break;
|
|
329
|
+
case "with":
|
|
330
|
+
return function(...options2) {
|
|
331
|
+
if (body) {
|
|
332
|
+
options2.unshift({ body });
|
|
333
|
+
}
|
|
334
|
+
return request(target, ...options2);
|
|
335
|
+
};
|
|
336
|
+
break;
|
|
337
|
+
case "body":
|
|
338
|
+
if (!body) {
|
|
339
|
+
body = target.body;
|
|
340
|
+
}
|
|
341
|
+
if (body) {
|
|
342
|
+
if (body[Symbol.metroProxy]) {
|
|
343
|
+
return body;
|
|
344
|
+
}
|
|
345
|
+
return bodyProxy(body, target);
|
|
346
|
+
}
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
if (target[prop] instanceof Function) {
|
|
350
|
+
return target[prop].bind(target);
|
|
351
|
+
}
|
|
352
|
+
return target[prop];
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function getResponseParams(res, current) {
|
|
357
|
+
let params2 = current || {};
|
|
358
|
+
if (!params2.url && current.url) {
|
|
359
|
+
params2.url = current.url;
|
|
360
|
+
}
|
|
361
|
+
for (let prop of ["status", "statusText", "headers", "body", "url", "type", "redirected"]) {
|
|
362
|
+
let value = res[prop];
|
|
363
|
+
if (typeof value == "undefined" || value == null) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (value?.[Symbol.metroProxy]) {
|
|
367
|
+
value = value[Symbol.metroSource];
|
|
368
|
+
}
|
|
369
|
+
if (typeof value == "function") {
|
|
370
|
+
value(params2[prop], params2);
|
|
371
|
+
} else {
|
|
372
|
+
if (prop == "url") {
|
|
373
|
+
params2.url = new URL(value, params2.url || "https://localhost/");
|
|
374
|
+
} else {
|
|
375
|
+
params2[prop] = value;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return params2;
|
|
380
|
+
}
|
|
381
|
+
function response(...options) {
|
|
382
|
+
let responseParams = {};
|
|
383
|
+
for (let option of options) {
|
|
384
|
+
if (typeof option == "string") {
|
|
385
|
+
responseParams.body = option;
|
|
386
|
+
} else if (option instanceof Response) {
|
|
387
|
+
Object.assign(responseParams, getResponseParams(option, responseParams));
|
|
388
|
+
} else if (option && typeof option == "object") {
|
|
389
|
+
if (option instanceof FormData || option instanceof Blob || option instanceof ArrayBuffer || option instanceof DataView || option instanceof ReadableStream || option instanceof URLSearchParams || option instanceof String || typeof TypedArray != "undefined" && option instanceof TypedArray) {
|
|
390
|
+
responseParams.body = option;
|
|
391
|
+
} else {
|
|
392
|
+
Object.assign(responseParams, getResponseParams(option, responseParams));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
let r = new Response(responseParams.body, responseParams);
|
|
397
|
+
Object.freeze(r);
|
|
398
|
+
return new Proxy(r, {
|
|
399
|
+
get(target, prop, receiver) {
|
|
400
|
+
switch (prop) {
|
|
401
|
+
case Symbol.metroProxy:
|
|
402
|
+
return true;
|
|
403
|
+
break;
|
|
404
|
+
case Symbol.metroSource:
|
|
405
|
+
return target;
|
|
406
|
+
break;
|
|
407
|
+
case "with":
|
|
408
|
+
return function(...options2) {
|
|
409
|
+
return response(target, ...options2);
|
|
410
|
+
};
|
|
411
|
+
break;
|
|
412
|
+
case "body":
|
|
413
|
+
if (responseParams.body) {
|
|
414
|
+
if (responseParams.body[Symbol.metroProxy]) {
|
|
415
|
+
return responseParams.body;
|
|
416
|
+
}
|
|
417
|
+
return bodyProxy(responseParams.body, target);
|
|
418
|
+
} else {
|
|
419
|
+
return bodyProxy("", target);
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
422
|
+
case "ok":
|
|
423
|
+
return target.status >= 200 && target.status < 400;
|
|
424
|
+
break;
|
|
425
|
+
case "headers":
|
|
426
|
+
return target.headers;
|
|
427
|
+
break;
|
|
428
|
+
default:
|
|
429
|
+
if (prop in responseParams && prop != "toString") {
|
|
430
|
+
return responseParams[prop];
|
|
431
|
+
}
|
|
432
|
+
if (prop in target && prop != "toString") {
|
|
433
|
+
if (typeof target[prop] == "function") {
|
|
434
|
+
return function(...args) {
|
|
435
|
+
return target[prop].apply(target, args);
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return target[prop];
|
|
439
|
+
}
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
return void 0;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
function appendSearchParams(url2, params2) {
|
|
447
|
+
if (typeof params2 == "function") {
|
|
448
|
+
params2(url2.searchParams, url2);
|
|
449
|
+
} else {
|
|
450
|
+
params2 = new URLSearchParams(params2);
|
|
451
|
+
params2.forEach((value, key) => {
|
|
452
|
+
url2.searchParams.append(key, value);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function url(...options) {
|
|
457
|
+
let validParams = [
|
|
458
|
+
"hash",
|
|
459
|
+
"host",
|
|
460
|
+
"hostname",
|
|
461
|
+
"href",
|
|
462
|
+
"password",
|
|
463
|
+
"pathname",
|
|
464
|
+
"port",
|
|
465
|
+
"protocol",
|
|
466
|
+
"username",
|
|
467
|
+
"search",
|
|
468
|
+
"searchParams"
|
|
469
|
+
];
|
|
470
|
+
let u = new URL("https://localhost/");
|
|
471
|
+
for (let option of options) {
|
|
472
|
+
if (typeof option == "string" || option instanceof String) {
|
|
473
|
+
u = new URL(option, u);
|
|
474
|
+
} else if (option instanceof URL || typeof Location != "undefined" && option instanceof Location) {
|
|
475
|
+
u = new URL(option);
|
|
476
|
+
} else if (option instanceof URLSearchParams) {
|
|
477
|
+
appendSearchParams(u, option);
|
|
478
|
+
} else if (option && typeof option == "object") {
|
|
479
|
+
for (let param in option) {
|
|
480
|
+
if (param == "search") {
|
|
481
|
+
if (typeof option.search == "function") {
|
|
482
|
+
option.search(u.search, u);
|
|
483
|
+
} else {
|
|
484
|
+
u.search = new URLSearchParams(option.search);
|
|
485
|
+
}
|
|
486
|
+
} else if (param == "searchParams") {
|
|
487
|
+
appendSearchParams(u, option.searchParams);
|
|
488
|
+
} else {
|
|
489
|
+
if (!validParams.includes(param)) {
|
|
490
|
+
throw metroError("metro.url: unknown url parameter " + metroURL + "url/unknown-param-name/", param);
|
|
491
|
+
}
|
|
492
|
+
if (typeof option[param] == "function") {
|
|
493
|
+
option[param](u[param], u);
|
|
494
|
+
} else if (typeof option[param] == "string" || option[param] instanceof String || typeof option[param] == "number" || option[param] instanceof Number || typeof option[param] == "boolean" || option[param] instanceof Boolean) {
|
|
495
|
+
u[param] = "" + option[param];
|
|
496
|
+
} else if (typeof option[param] == "object" && option[param].toString) {
|
|
497
|
+
u[param] = option[param].toString();
|
|
498
|
+
} else {
|
|
499
|
+
throw metroError("metro.url: unsupported value for " + param + " " + metroURL + "url/unsupported-param-value/", options[param]);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
} else {
|
|
504
|
+
throw metroError("metro.url: unsupported option value " + metroURL + "url/unsupported-option-value/", option);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
Object.freeze(u);
|
|
508
|
+
return new Proxy(u, {
|
|
509
|
+
get(target, prop, receiver) {
|
|
510
|
+
switch (prop) {
|
|
511
|
+
case Symbol.metroProxy:
|
|
512
|
+
return true;
|
|
513
|
+
break;
|
|
514
|
+
case Symbol.metroSource:
|
|
515
|
+
return target;
|
|
516
|
+
break;
|
|
517
|
+
case "with":
|
|
518
|
+
return function(...options2) {
|
|
519
|
+
return url(target, ...options2);
|
|
520
|
+
};
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
if (target[prop] instanceof Function) {
|
|
524
|
+
return target[prop].bind(target);
|
|
525
|
+
}
|
|
526
|
+
return target[prop];
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function formdata(...options) {
|
|
531
|
+
var params2 = new FormData();
|
|
532
|
+
for (let option of options) {
|
|
533
|
+
if (option instanceof FormData) {
|
|
534
|
+
for (let entry of option.entries()) {
|
|
535
|
+
params2.append(entry[0], entry[1]);
|
|
536
|
+
}
|
|
537
|
+
} else if (option && typeof option == "object") {
|
|
538
|
+
for (let entry of Object.entries(option)) {
|
|
539
|
+
if (Array.isArray(entry[1])) {
|
|
540
|
+
for (let value of entry[1]) {
|
|
541
|
+
params2.append(entry[0], value);
|
|
542
|
+
}
|
|
543
|
+
} else {
|
|
544
|
+
params2.append(entry[0], entry[1]);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
throw new metroError("metro.formdata: unknown option type, only FormData or Object supported", option);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
Object.freeze(params2);
|
|
552
|
+
return new Proxy(params2, {
|
|
553
|
+
get: (target, prop, receiver) => {
|
|
554
|
+
switch (prop) {
|
|
555
|
+
case Symbol.metroProxy:
|
|
556
|
+
return true;
|
|
557
|
+
break;
|
|
558
|
+
case Symbol.metroSource:
|
|
559
|
+
return target;
|
|
560
|
+
break;
|
|
561
|
+
case "with":
|
|
562
|
+
return function(...options2) {
|
|
563
|
+
return formdata(target, ...options2);
|
|
564
|
+
};
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
if (target[prop] instanceof Function) {
|
|
568
|
+
return target[prop].bind(target);
|
|
569
|
+
}
|
|
570
|
+
return target[prop];
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
var metroConsole = {
|
|
575
|
+
error: (message, ...details) => {
|
|
576
|
+
console.error("\u24C2\uFE0F ", message, ...details);
|
|
577
|
+
},
|
|
578
|
+
info: (message, ...details) => {
|
|
579
|
+
console.info("\u24C2\uFE0F ", message, ...details);
|
|
580
|
+
},
|
|
581
|
+
group: (name) => {
|
|
582
|
+
console.group("\u24C2\uFE0F " + name);
|
|
583
|
+
},
|
|
584
|
+
groupEnd: (name) => {
|
|
585
|
+
console.groupEnd("\u24C2\uFE0F " + name);
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
function metroError(message, ...details) {
|
|
589
|
+
metroConsole.error(message, ...details);
|
|
590
|
+
return new Error(message, ...details);
|
|
591
|
+
}
|
|
592
|
+
var trace = {
|
|
593
|
+
/**
|
|
594
|
+
* Adds a named tracer function
|
|
595
|
+
* @param {string} name - the name of the tracer
|
|
596
|
+
* @param {Function} tracer - the tracer function to call
|
|
597
|
+
*/
|
|
598
|
+
add(name, tracer) {
|
|
599
|
+
Client.tracers[name] = tracer;
|
|
600
|
+
},
|
|
601
|
+
/**
|
|
602
|
+
* Removes a named tracer function
|
|
603
|
+
* @param {string} name
|
|
604
|
+
*/
|
|
605
|
+
delete(name) {
|
|
606
|
+
delete Client.tracers[name];
|
|
607
|
+
},
|
|
608
|
+
/**
|
|
609
|
+
* Removes all tracer functions
|
|
610
|
+
*/
|
|
611
|
+
clear() {
|
|
612
|
+
Client.tracers = {};
|
|
613
|
+
},
|
|
614
|
+
/**
|
|
615
|
+
* Returns a set of request and response tracer functions that use the
|
|
616
|
+
* console.group feature to shows nested request/response pairs, with
|
|
617
|
+
* most commonly needed information for debugging
|
|
618
|
+
*/
|
|
619
|
+
group() {
|
|
620
|
+
let group = 0;
|
|
621
|
+
return {
|
|
622
|
+
request: (req, middleware) => {
|
|
623
|
+
group++;
|
|
624
|
+
metroConsole.group(group);
|
|
625
|
+
metroConsole.info(req?.url, req, middleware);
|
|
626
|
+
},
|
|
627
|
+
response: (res, middleware) => {
|
|
628
|
+
metroConsole.info(res?.body ? res.body[Symbol.metroSource] : null, res, middleware);
|
|
629
|
+
metroConsole.groupEnd(group);
|
|
630
|
+
group--;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// node_modules/@muze-nl/metro/src/mw/json.mjs
|
|
637
|
+
function jsonmw(options) {
|
|
638
|
+
options = Object.assign({
|
|
639
|
+
reviver: null,
|
|
640
|
+
replacer: null,
|
|
641
|
+
space: ""
|
|
642
|
+
}, options);
|
|
643
|
+
return async (req, next) => {
|
|
644
|
+
if (["POST", "PUT", "PATCH", "QUERY"].includes(req.method)) {
|
|
645
|
+
req = req.with({
|
|
646
|
+
headers: {
|
|
647
|
+
"Content-Type": "application/json",
|
|
648
|
+
"Accept": "application/json"
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
if (req.body && typeof req.body[Symbol.metroSource] == "object") {
|
|
652
|
+
req = req.with({
|
|
653
|
+
body: JSON.stringify(req.body[Symbol.metroSource], options.replacer, options.space)
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
} else {
|
|
657
|
+
req = req.with({
|
|
658
|
+
headers: {
|
|
659
|
+
"Accept": "application/json"
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
let res = await next(req);
|
|
664
|
+
let body = await res.text();
|
|
665
|
+
let json = JSON.parse(body, options.reviver);
|
|
666
|
+
return res.with({
|
|
667
|
+
body: json
|
|
668
|
+
});
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// node_modules/@muze-nl/metro/src/mw/thrower.mjs
|
|
673
|
+
function thrower(options) {
|
|
674
|
+
return async (req, next) => {
|
|
675
|
+
let res = await next(req);
|
|
676
|
+
if (!res.ok) {
|
|
677
|
+
if (options && typeof options[res.status] == "function") {
|
|
678
|
+
res = options[res.status].apply(res, req);
|
|
679
|
+
} else {
|
|
680
|
+
throw new Error(res.status + ": " + res.statusText, {
|
|
681
|
+
cause: res
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return res;
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// node_modules/@muze-nl/metro/src/everything.mjs
|
|
690
|
+
var metro = Object.assign({}, metro_exports, {
|
|
691
|
+
mw: {
|
|
692
|
+
jsonmw,
|
|
693
|
+
thrower
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
globalThis.metro = metro;
|
|
697
|
+
var everything_default = metro;
|
|
698
|
+
|
|
699
|
+
// node_modules/@muze-nl/assert/src/assert.mjs
|
|
700
|
+
globalThis.assertEnabled = false;
|
|
701
|
+
function assert(source, test) {
|
|
702
|
+
if (globalThis.assertEnabled) {
|
|
703
|
+
let problems = fails(source, test);
|
|
704
|
+
if (problems) {
|
|
705
|
+
console.error("\u{1F170}\uFE0F Assertions failed because of:", problems, "in this source:", source);
|
|
706
|
+
throw new Error("Assertions failed", {
|
|
707
|
+
cause: { problems, source }
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
function Optional(pattern) {
|
|
713
|
+
return function _Optional(data, root, path) {
|
|
714
|
+
if (typeof data != "undefined" && data != null && typeof pattern != "undefined") {
|
|
715
|
+
return fails(data, pattern, root, path);
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function Required(pattern) {
|
|
720
|
+
return function _Required(data, root, path) {
|
|
721
|
+
if (data == null || typeof data == "undefined") {
|
|
722
|
+
return error("data is required", data, pattern || "any value", path);
|
|
723
|
+
} else if (typeof pattern != "undefined") {
|
|
724
|
+
return fails(data, pattern, root, path);
|
|
725
|
+
} else {
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
function Recommended(pattern) {
|
|
731
|
+
return function _Recommended(data, root, path) {
|
|
732
|
+
if (data == null || typeof data == "undefined") {
|
|
733
|
+
console.warn("data does not contain recommended value", data, pattern, path);
|
|
734
|
+
return false;
|
|
735
|
+
} else {
|
|
736
|
+
return fails(data, pattern, root, path);
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function oneOf(...patterns) {
|
|
741
|
+
return function _oneOf(data, root, path) {
|
|
742
|
+
for (let pattern of patterns) {
|
|
743
|
+
if (!fails(data, pattern, root, path)) {
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return error("data does not match oneOf patterns", data, patterns, path);
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function anyOf(...patterns) {
|
|
751
|
+
return function _anyOf(data, root, path) {
|
|
752
|
+
if (!Array.isArray(data)) {
|
|
753
|
+
return error("data is not an array", data, "anyOf", path);
|
|
754
|
+
}
|
|
755
|
+
for (let value of data) {
|
|
756
|
+
if (oneOf(...patterns)(value)) {
|
|
757
|
+
return error("data does not match anyOf patterns", value, patterns, path);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return false;
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
function allOf(...patterns) {
|
|
764
|
+
return function _allOf(data, root, path) {
|
|
765
|
+
let problems = [];
|
|
766
|
+
for (let pattern of patterns) {
|
|
767
|
+
problems = problems.concat(fails(data, pattern, root, path));
|
|
768
|
+
}
|
|
769
|
+
problems = problems.filter(Boolean);
|
|
770
|
+
if (problems.length) {
|
|
771
|
+
return error("data does not match all given patterns", data, patterns, path, problems);
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
function validURL(data, root, path) {
|
|
776
|
+
try {
|
|
777
|
+
if (data instanceof URL) {
|
|
778
|
+
data = data.href;
|
|
779
|
+
}
|
|
780
|
+
let url2 = new URL(data);
|
|
781
|
+
if (url2.href != data) {
|
|
782
|
+
if (!(url2.href + "/" == data || url2.href == data + "/")) {
|
|
783
|
+
return error("data is not a valid url", data, "validURL", path);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
} catch (e) {
|
|
787
|
+
return error("data is not a valid url", data, "validURL", path);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
function validEmail(data, root, path) {
|
|
791
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
|
|
792
|
+
return error("data is not a valid email", data, "validEmail", path);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function instanceOf(constructor) {
|
|
796
|
+
return function _instanceOf(data, root, path) {
|
|
797
|
+
if (!(data instanceof constructor)) {
|
|
798
|
+
return error("data is not an instanceof pattern", data, constructor, path);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function not(pattern) {
|
|
803
|
+
return function _not(data, root, path) {
|
|
804
|
+
if (!fails(data, pattern, root, path)) {
|
|
805
|
+
return error("data matches pattern, when required not to", data, pattern, path);
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
function fails(data, pattern, root, path = "") {
|
|
810
|
+
if (!root) {
|
|
811
|
+
root = data;
|
|
812
|
+
}
|
|
813
|
+
let problems = [];
|
|
814
|
+
if (pattern === Boolean) {
|
|
815
|
+
if (typeof data != "boolean" && !(data instanceof Boolean)) {
|
|
816
|
+
problems.push(error("data is not a boolean", data, pattern, path));
|
|
817
|
+
}
|
|
818
|
+
} else if (pattern === Number) {
|
|
819
|
+
if (typeof data != "number" && !(data instanceof Number)) {
|
|
820
|
+
problems.push(error("data is not a number", data, pattern, path));
|
|
821
|
+
}
|
|
822
|
+
} else if (pattern === String) {
|
|
823
|
+
if (typeof data != "string" && !(data instanceof String)) {
|
|
824
|
+
problems.push(error("data is not a string", data, pattern, path));
|
|
825
|
+
}
|
|
826
|
+
if (data == "") {
|
|
827
|
+
problems.push(error("data is an empty string, which is not allowed", data, pattern, path));
|
|
828
|
+
}
|
|
829
|
+
} else if (pattern instanceof RegExp) {
|
|
830
|
+
if (Array.isArray(data)) {
|
|
831
|
+
let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
|
|
832
|
+
if (index > -1) {
|
|
833
|
+
problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
|
|
834
|
+
}
|
|
835
|
+
} else if (typeof data == "undefined") {
|
|
836
|
+
problems.push(error("data is undefined, should match pattern", data, pattern, path));
|
|
837
|
+
} else if (!pattern.test(data)) {
|
|
838
|
+
problems.push(error("data does not match pattern", data, pattern, path));
|
|
839
|
+
}
|
|
840
|
+
} else if (pattern instanceof Function) {
|
|
841
|
+
let problem = pattern(data, root, path);
|
|
842
|
+
if (problem) {
|
|
843
|
+
if (Array.isArray(problem)) {
|
|
844
|
+
problems = problems.concat(problem);
|
|
845
|
+
} else {
|
|
846
|
+
problems.push(problem);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
} else if (Array.isArray(pattern)) {
|
|
850
|
+
if (!Array.isArray(data)) {
|
|
851
|
+
problems.push(error("data is not an array", data, [], path));
|
|
852
|
+
}
|
|
853
|
+
for (let p2 of pattern) {
|
|
854
|
+
for (let index of data.keys()) {
|
|
855
|
+
let problem = fails(data[index], p2, root, path + "[" + index + "]");
|
|
856
|
+
if (Array.isArray(problem)) {
|
|
857
|
+
problems = problems.concat(problem);
|
|
858
|
+
} else if (problem) {
|
|
859
|
+
problems.push(problem);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
} else if (pattern && typeof pattern == "object") {
|
|
864
|
+
if (Array.isArray(data)) {
|
|
865
|
+
let index = data.findIndex((element, index2) => fails(element, pattern, root, path + "[" + index2 + "]"));
|
|
866
|
+
if (index > -1) {
|
|
867
|
+
problems.push(error("data[" + index + "] does not match pattern", data[index], pattern, path + "[" + index + "]"));
|
|
868
|
+
}
|
|
869
|
+
} else if (!data || typeof data != "object") {
|
|
870
|
+
problems.push(error("data is not an object, pattern is", data, pattern, path));
|
|
871
|
+
} else {
|
|
872
|
+
if (data instanceof URLSearchParams) {
|
|
873
|
+
data = Object.fromEntries(data);
|
|
874
|
+
}
|
|
875
|
+
if (pattern instanceof Function) {
|
|
876
|
+
let result = fails(data, pattern, root, path);
|
|
877
|
+
if (result) {
|
|
878
|
+
problems = problems.concat(result);
|
|
879
|
+
}
|
|
880
|
+
} else {
|
|
881
|
+
for (const [wKey, wVal] of Object.entries(pattern)) {
|
|
882
|
+
let result = fails(data[wKey], wVal, root, path + "." + wKey);
|
|
883
|
+
if (result) {
|
|
884
|
+
problems = problems.concat(result);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
} else {
|
|
890
|
+
if (pattern != data) {
|
|
891
|
+
problems.push(error("data and pattern are not equal", data, pattern, path));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
if (problems.length) {
|
|
895
|
+
return problems;
|
|
896
|
+
}
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
function error(message, found, expected, path, problems) {
|
|
900
|
+
let result = {
|
|
901
|
+
message,
|
|
902
|
+
found,
|
|
903
|
+
expected,
|
|
904
|
+
path
|
|
905
|
+
};
|
|
906
|
+
if (problems) {
|
|
907
|
+
result.problems = problems;
|
|
908
|
+
}
|
|
909
|
+
return result;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// src/oidc.util.mjs
|
|
913
|
+
var MustHave = (...options) => (value, root) => {
|
|
914
|
+
if (options.filter((o) => root.hasOwnKey(o)).length > 0) {
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
917
|
+
return error("root data must have all of", root, options);
|
|
918
|
+
};
|
|
919
|
+
var MustInclude = (...options) => (value) => {
|
|
920
|
+
if (Array.isArray(value) && options.filter((o) => !value.includes(o)).length == 0) {
|
|
921
|
+
return false;
|
|
922
|
+
} else {
|
|
923
|
+
return error("data must be an array which includes", value, options);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
var validJWA = [
|
|
927
|
+
"HS256",
|
|
928
|
+
"HS384",
|
|
929
|
+
"HS512",
|
|
930
|
+
"RS256",
|
|
931
|
+
"RS384",
|
|
932
|
+
"RS512",
|
|
933
|
+
"ES256",
|
|
934
|
+
"ES384",
|
|
935
|
+
"ES512"
|
|
936
|
+
];
|
|
937
|
+
var validAuthMethods = [
|
|
938
|
+
"client_secret_post",
|
|
939
|
+
"client_secret_basic",
|
|
940
|
+
"client_secret_jwt",
|
|
941
|
+
"private_key_jwt"
|
|
942
|
+
];
|
|
943
|
+
|
|
944
|
+
// src/oidc.discovery.mjs
|
|
945
|
+
async function oidcDiscovery(options = {}) {
|
|
946
|
+
assert(options, {
|
|
947
|
+
client: Optional(instanceOf(everything_default.client().constructor)),
|
|
948
|
+
issuer: Required(validURL)
|
|
949
|
+
});
|
|
950
|
+
const defaultOptions = {
|
|
951
|
+
client: everything_default.client().with(thrower()).with(jsonmw()),
|
|
952
|
+
requireDynamicRegistration: false
|
|
953
|
+
};
|
|
954
|
+
options = Object.assign({}, defaultOptions, options);
|
|
955
|
+
const TestSucceeded = false;
|
|
956
|
+
function MustUseHTTPS(url2) {
|
|
957
|
+
return TestSucceeded;
|
|
958
|
+
}
|
|
959
|
+
const openid_provider_metadata = {
|
|
960
|
+
issuer: Required(allOf(options.issuer, MustUseHTTPS)),
|
|
961
|
+
authorization_endpoint: Required(validURL),
|
|
962
|
+
token_endpoint: Required(validURL),
|
|
963
|
+
userinfo_endpoint: Recommended(validURL),
|
|
964
|
+
// todo: test for https protocol
|
|
965
|
+
jwks_uri: Required(validURL),
|
|
966
|
+
registration_endpoint: options.requireDynamicRegistration ? Required(validURL) : Recommended(validURL),
|
|
967
|
+
scopes_supported: Recommended(MustInclude("openid")),
|
|
968
|
+
response_types_supported: options.requireDynamicRegistration ? Required(MustInclude("code", "id_token", "id_token token")) : Required([]),
|
|
969
|
+
response_modes_supported: Optional([]),
|
|
970
|
+
grant_types_supported: options.requireDynamicRegistration ? Optional(MustInclude("authorization_code")) : Optional([]),
|
|
971
|
+
acr_values_supported: Optional([]),
|
|
972
|
+
subject_types_supported: Required([]),
|
|
973
|
+
id_token_signing_alg_values_supported: Required(MustInclude("RS256")),
|
|
974
|
+
id_token_encryption_alg_values_supported: Optional([]),
|
|
975
|
+
id_token_encryption_enc_values_supported: Optional([]),
|
|
976
|
+
userinfo_signing_alg_values_supported: Optional([]),
|
|
977
|
+
userinfo_encryption_alg_values_supported: Optional([]),
|
|
978
|
+
userinfo_encryption_enc_values_supported: Optional([]),
|
|
979
|
+
request_object_signing_alg_values_supported: Optional(MustInclude("RS256")),
|
|
980
|
+
// not testing for 'none'
|
|
981
|
+
request_object_encryption_alg_values_supported: Optional([]),
|
|
982
|
+
request_object_encryption_enc_values_supported: Optional([]),
|
|
983
|
+
token_endpoint_auth_methods_supported: Optional(anyOf(...validAuthMethods)),
|
|
984
|
+
token_endpoint_auth_signing_alg_values_supported: Optional(MustInclude("RS256"), not(MustInclude("none"))),
|
|
985
|
+
display_values_supported: Optional(anyOf("page", "popup", "touch", "wap")),
|
|
986
|
+
claim_types_supported: Optional(anyOf("normal", "aggregated", "distributed")),
|
|
987
|
+
claims_supported: Recommended([]),
|
|
988
|
+
service_documentation: Optional(validURL),
|
|
989
|
+
claims_locales_supported: Optional([]),
|
|
990
|
+
ui_locales_supported: Optional([]),
|
|
991
|
+
claims_parameter_supported: Optional(Boolean),
|
|
992
|
+
request_parameter_supported: Optional(Boolean),
|
|
993
|
+
request_uri_parameter_supported: Optional(Boolean),
|
|
994
|
+
op_policy_uri: Optional(validURL),
|
|
995
|
+
op_tos_uri: Optional(validURL)
|
|
996
|
+
};
|
|
997
|
+
const configURL = everything_default.url(options.issuer, ".well-known/openid-configuration");
|
|
998
|
+
const response2 = await options.client.get(
|
|
999
|
+
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
|
|
1000
|
+
// note: this allows path components in the options.issuer url
|
|
1001
|
+
configURL
|
|
1002
|
+
);
|
|
1003
|
+
const openid_config = response2.body[Symbol.metroSource];
|
|
1004
|
+
assert(openid_config, openid_provider_metadata);
|
|
1005
|
+
assert(openid_config.issuer, options.issuer);
|
|
1006
|
+
return openid_config;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// src/oidc.register.mjs
|
|
1010
|
+
async function register(options) {
|
|
1011
|
+
const openid_client_metadata = {
|
|
1012
|
+
redirect_uris: Required([validURL]),
|
|
1013
|
+
response_types: Optional([]),
|
|
1014
|
+
grant_types: Optional(anyOf("authorization_code", "refresh_token")),
|
|
1015
|
+
//TODO: match response_types with grant_types
|
|
1016
|
+
application_type: Optional(oneOf("native", "web")),
|
|
1017
|
+
contacts: Optional([validEmail]),
|
|
1018
|
+
client_name: Optional(String),
|
|
1019
|
+
logo_uri: Optional(validURL),
|
|
1020
|
+
client_uri: Optional(validURL),
|
|
1021
|
+
policy_uri: Optional(validURL),
|
|
1022
|
+
tos_uri: Optional(validURL),
|
|
1023
|
+
jwks_uri: Optional(validURL, not(MustHave("jwks"))),
|
|
1024
|
+
jwks: Optional(validURL, not(MustHave("jwks_uri"))),
|
|
1025
|
+
sector_identifier_uri: Optional(validURL),
|
|
1026
|
+
subject_type: Optional(String),
|
|
1027
|
+
id_token_signed_response_alg: Optional(oneOf(...validJWA)),
|
|
1028
|
+
id_token_encrypted_response_alg: Optional(oneOf(...validJWA)),
|
|
1029
|
+
id_token_encrypted_response_enc: Optional(oneOf(...validJWA), MustHave("id_token_encrypted_response_alg")),
|
|
1030
|
+
userinfo_signed_response_alg: Optional(oneOf(...validJWA)),
|
|
1031
|
+
userinfo_encrypted_response_alg: Optional(oneOf(...validJWA)),
|
|
1032
|
+
userinfo_encrypted_response_enc: Optional(oneOf(...validJWA), MustHave("userinfo_encrypted_response_alg")),
|
|
1033
|
+
request_object_signing_alg: Optional(oneOf(...validJWA)),
|
|
1034
|
+
request_object_encryption_alg: Optional(oneOf(...validJWA)),
|
|
1035
|
+
request_object_encryption_enc: Optional(oneOf(...validJWA)),
|
|
1036
|
+
token_endpoint_auth_method: Optional(oneOf(...validAuthMethods)),
|
|
1037
|
+
token_endpoint_auth_signing_alg: Optional(oneOf(...validJWA)),
|
|
1038
|
+
default_max_age: Optional(Number),
|
|
1039
|
+
require_auth_time: Optional(Boolean),
|
|
1040
|
+
default_acr_values: Optional([String]),
|
|
1041
|
+
initiate_login_uri: Optional([validURL]),
|
|
1042
|
+
request_uris: Optional([validURL])
|
|
1043
|
+
};
|
|
1044
|
+
assert(options, {
|
|
1045
|
+
client: Optional(instanceOf(everything_default.client().constructor)),
|
|
1046
|
+
registration_endpoint: validURL,
|
|
1047
|
+
client_info: openid_client_metadata
|
|
1048
|
+
});
|
|
1049
|
+
const defaultOptions = {
|
|
1050
|
+
client: everything_default.client().with(thrower()).with(jsonmw())
|
|
1051
|
+
};
|
|
1052
|
+
options = Object.assign({}, defaultOptions, options);
|
|
1053
|
+
let response2 = await options.client.post(options.registration_endpoint, {
|
|
1054
|
+
body: options.client_info
|
|
1055
|
+
});
|
|
1056
|
+
let info = response2.body;
|
|
1057
|
+
if (!info.client_id || !info.client_secret) {
|
|
1058
|
+
throw everything_default.metroError("metro.oidc: Error: dynamic registration of client failed, no client_id or client_secret returned", response2);
|
|
1059
|
+
}
|
|
1060
|
+
options.client_info = Object.assign(options.client_info, info);
|
|
1061
|
+
return options.client_info;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// node_modules/@muze-nl/metro-oauth2/src/oauth2.mjs
|
|
1065
|
+
var oauth2_exports = {};
|
|
1066
|
+
__export(oauth2_exports, {
|
|
1067
|
+
base64url_encode: () => base64url_encode,
|
|
1068
|
+
createState: () => createState,
|
|
1069
|
+
default: () => oauth2mw,
|
|
1070
|
+
generateCodeChallenge: () => generateCodeChallenge,
|
|
1071
|
+
generateCodeVerifier: () => generateCodeVerifier,
|
|
1072
|
+
getExpires: () => getExpires,
|
|
1073
|
+
isExpired: () => isExpired,
|
|
1074
|
+
isRedirected: () => isRedirected
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// node_modules/@muze-nl/metro-oauth2/node_modules/@muze-nl/assert/src/assert.mjs
|
|
1078
|
+
globalThis.assertEnabled = false;
|
|
1079
|
+
var assert2 = (source, test) => {
|
|
1080
|
+
if (globalThis.assertEnabled) {
|
|
1081
|
+
let problems = fails2(source, test);
|
|
1082
|
+
if (problems) {
|
|
1083
|
+
throw new assertError("Assertions failed", problems, source);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
var Optional2 = (pattern) => (data) => data == null || typeof data == "undefined" ? false : fails2(data, pattern);
|
|
1088
|
+
var Required2 = (pattern) => (data) => fails2(data, pattern);
|
|
1089
|
+
var Recommended2 = (pattern) => (data) => data == null || typeof data == "undefined" ? (() => {
|
|
1090
|
+
console.warning("data does not contain recommended value", data, pattern);
|
|
1091
|
+
return false;
|
|
1092
|
+
})() : fails2(data, pattern);
|
|
1093
|
+
var oneOf2 = (...patterns) => (data) => {
|
|
1094
|
+
for (let pattern of patterns) {
|
|
1095
|
+
if (!fails2(data, pattern)) {
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return error2("data does not match oneOf patterns", data, patterns);
|
|
1100
|
+
};
|
|
1101
|
+
var anyOf2 = (...patterns) => (data) => {
|
|
1102
|
+
if (!Array.isArray(data)) {
|
|
1103
|
+
return error2("data is not an array", data, "anyOf");
|
|
1104
|
+
}
|
|
1105
|
+
for (let value of data) {
|
|
1106
|
+
if (oneOf2(...patterns)(value)) {
|
|
1107
|
+
return error2("data does not match anyOf patterns", value, patterns);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
return false;
|
|
1111
|
+
};
|
|
1112
|
+
function validURL2(data) {
|
|
1113
|
+
try {
|
|
1114
|
+
if (data instanceof URL) {
|
|
1115
|
+
data = data.href;
|
|
1116
|
+
}
|
|
1117
|
+
let url2 = new URL(data);
|
|
1118
|
+
if (url2.href != data) {
|
|
1119
|
+
return error2("data is not a valid url", data, "validURL");
|
|
1120
|
+
}
|
|
1121
|
+
} catch (e) {
|
|
1122
|
+
return error2("data is not a valid url", data, "validURL");
|
|
1123
|
+
}
|
|
1124
|
+
return false;
|
|
1125
|
+
}
|
|
1126
|
+
function fails2(data, pattern, root) {
|
|
1127
|
+
if (!root) {
|
|
1128
|
+
root = data;
|
|
1129
|
+
}
|
|
1130
|
+
let problems = [];
|
|
1131
|
+
if (pattern === Boolean) {
|
|
1132
|
+
if (typeof data != "boolean") {
|
|
1133
|
+
problems.push(error2("data is not a boolean", data, pattern));
|
|
1134
|
+
}
|
|
1135
|
+
} else if (pattern === Number) {
|
|
1136
|
+
if (typeof data != "number") {
|
|
1137
|
+
problems.push(error2("data is not a number", data, pattern));
|
|
1138
|
+
}
|
|
1139
|
+
} else if (pattern instanceof RegExp) {
|
|
1140
|
+
if (Array.isArray(data)) {
|
|
1141
|
+
let index = data.findIndex((element) => fails2(element, pattern, root));
|
|
1142
|
+
if (index > -1) {
|
|
1143
|
+
problems.push(error2("data[" + index + "] does not match pattern", data[index], pattern));
|
|
1144
|
+
}
|
|
1145
|
+
} else if (!pattern.test(data)) {
|
|
1146
|
+
problems.push(error2("data does not match pattern", data, pattern));
|
|
1147
|
+
}
|
|
1148
|
+
} else if (pattern instanceof Function) {
|
|
1149
|
+
if (pattern(data, root)) {
|
|
1150
|
+
problems.push(error2("data does not match function", data, pattern));
|
|
1151
|
+
}
|
|
1152
|
+
} else if (Array.isArray(pattern)) {
|
|
1153
|
+
if (!Array.isArray(data)) {
|
|
1154
|
+
problems.push(error2("data is not an array", data, []));
|
|
1155
|
+
}
|
|
1156
|
+
for (p of pattern) {
|
|
1157
|
+
let problem = fails2(data, p, root);
|
|
1158
|
+
if (Array.isArray(problem)) {
|
|
1159
|
+
problems.concat(problem);
|
|
1160
|
+
} else if (problem) {
|
|
1161
|
+
problems.push(problem);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
} else if (pattern && typeof pattern == "object") {
|
|
1165
|
+
if (Array.isArray(data)) {
|
|
1166
|
+
let index = data.findIndex((element) => fails2(element, pattern, root));
|
|
1167
|
+
if (index > -1) {
|
|
1168
|
+
problems.push(error2("data[" + index + "] does not match pattern", data[index], pattern));
|
|
1169
|
+
}
|
|
1170
|
+
} else if (!data || typeof data != "object") {
|
|
1171
|
+
problems.push(error2("data is not an object, pattern is", data, pattern));
|
|
1172
|
+
} else {
|
|
1173
|
+
if (data instanceof URLSearchParams) {
|
|
1174
|
+
data = Object.fromEntries(data);
|
|
1175
|
+
}
|
|
1176
|
+
let p2 = problems[problems.length - 1];
|
|
1177
|
+
for (const [wKey, wVal] of Object.entries(pattern)) {
|
|
1178
|
+
let result = fails2(data[wKey], wVal, root);
|
|
1179
|
+
if (result) {
|
|
1180
|
+
if (!p2 || typeof p2 == "string") {
|
|
1181
|
+
p2 = {};
|
|
1182
|
+
problems.push(error2(p2, data[wKey], wVal));
|
|
1183
|
+
}
|
|
1184
|
+
p2[wKey] = result.problems;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
} else {
|
|
1189
|
+
if (pattern != data) {
|
|
1190
|
+
problems.push(error2("data and pattern are not equal", data, pattern));
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (problems.length) {
|
|
1194
|
+
return problems;
|
|
1195
|
+
}
|
|
1196
|
+
return false;
|
|
1197
|
+
}
|
|
1198
|
+
var assertError = class extends Error {
|
|
1199
|
+
constructor(message, problems, ...details) {
|
|
1200
|
+
super(message);
|
|
1201
|
+
this.problems = problems;
|
|
1202
|
+
this.details = details;
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
1205
|
+
function error2(message, found, expected) {
|
|
1206
|
+
return {
|
|
1207
|
+
message,
|
|
1208
|
+
found,
|
|
1209
|
+
expected
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// node_modules/@muze-nl/metro-oauth2/src/tokenstore.mjs
|
|
1214
|
+
function tokenStore(site) {
|
|
1215
|
+
let localState, localTokens;
|
|
1216
|
+
if (typeof localStorage !== "undefined") {
|
|
1217
|
+
localState = {
|
|
1218
|
+
get: () => localStorage.getItem("metro/state:" + site),
|
|
1219
|
+
set: (value) => localStorage.setItem("metro/state:" + site, value),
|
|
1220
|
+
has: () => localStorage.getItem("metro/state:" + site) !== null
|
|
1221
|
+
};
|
|
1222
|
+
localTokens = {
|
|
1223
|
+
get: (name) => JSON.parse(localStorage.getItem(site + ":" + name)),
|
|
1224
|
+
set: (name, value) => localStorage.setItem(site + ":" + name, JSON.stringify(value)),
|
|
1225
|
+
has: (name) => localStorage.getItem(site + ":" + name) !== null
|
|
1226
|
+
};
|
|
1227
|
+
} else {
|
|
1228
|
+
let stateMap = /* @__PURE__ */ new Map();
|
|
1229
|
+
localState = {
|
|
1230
|
+
get: () => stateMap.get("metro/state:" + site),
|
|
1231
|
+
set: (value) => stateMap.set("metro/state:" + site, value),
|
|
1232
|
+
has: () => stateMap.has("metro/state:" + site)
|
|
1233
|
+
};
|
|
1234
|
+
localTokens = /* @__PURE__ */ new Map();
|
|
1235
|
+
}
|
|
1236
|
+
return {
|
|
1237
|
+
state: localState,
|
|
1238
|
+
tokens: localTokens
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
// node_modules/@muze-nl/metro-oauth2/src/oauth2.mjs
|
|
1243
|
+
function oauth2mw(options) {
|
|
1244
|
+
const defaultOptions = {
|
|
1245
|
+
client: everything_default.client(),
|
|
1246
|
+
force_authorization: false,
|
|
1247
|
+
site: "default",
|
|
1248
|
+
oauth2_configuration: {
|
|
1249
|
+
authorization_endpoint: "/authorize",
|
|
1250
|
+
token_endpoint: "/token",
|
|
1251
|
+
redirect_uri: globalThis.document?.location.href,
|
|
1252
|
+
grant_type: "authorization_code",
|
|
1253
|
+
code_verifier: generateCodeVerifier(64)
|
|
1254
|
+
},
|
|
1255
|
+
callbacks: {
|
|
1256
|
+
authorize: async (url2) => {
|
|
1257
|
+
if (window.location.href != url2.href) {
|
|
1258
|
+
window.location.replace(url2.href);
|
|
1259
|
+
}
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
assert2(options, {});
|
|
1265
|
+
const oauth22 = Object.assign({}, defaultOptions.oauth2_configuration, options?.oauth2_configuration);
|
|
1266
|
+
options = Object.assign({}, defaultOptions, options);
|
|
1267
|
+
options.oauth2_configuration = oauth22;
|
|
1268
|
+
const store = tokenStore(options.site);
|
|
1269
|
+
if (!options.tokens) {
|
|
1270
|
+
options.tokens = store.tokens;
|
|
1271
|
+
}
|
|
1272
|
+
if (!options.state) {
|
|
1273
|
+
options.state = store.state;
|
|
1274
|
+
}
|
|
1275
|
+
assert2(options, {
|
|
1276
|
+
oauth2_configuration: {
|
|
1277
|
+
client_id: Required2(/.+/),
|
|
1278
|
+
grant_type: "authorization_code",
|
|
1279
|
+
authorization_endpoint: Required2(validURL2),
|
|
1280
|
+
token_endpoint: Required2(validURL2),
|
|
1281
|
+
redirect_uri: Required2(validURL2)
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
for (let option in oauth22) {
|
|
1285
|
+
switch (option) {
|
|
1286
|
+
case "access_token":
|
|
1287
|
+
case "authorization_code":
|
|
1288
|
+
case "refresh_token":
|
|
1289
|
+
options.tokens.set(option, oauth22[option]);
|
|
1290
|
+
break;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
return async function(req, next) {
|
|
1294
|
+
if (options.force_authorization) {
|
|
1295
|
+
return oauth2authorized(req, next);
|
|
1296
|
+
}
|
|
1297
|
+
let res;
|
|
1298
|
+
try {
|
|
1299
|
+
res = await next(req);
|
|
1300
|
+
if (res.ok) {
|
|
1301
|
+
return res;
|
|
1302
|
+
}
|
|
1303
|
+
} catch (err) {
|
|
1304
|
+
switch (res.status) {
|
|
1305
|
+
case 400:
|
|
1306
|
+
// Oauth2.1 RFC 3.2.4
|
|
1307
|
+
case 401:
|
|
1308
|
+
return oauth2authorized(req, next);
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
throw err;
|
|
1312
|
+
}
|
|
1313
|
+
if (!res.ok) {
|
|
1314
|
+
switch (res.status) {
|
|
1315
|
+
case 400:
|
|
1316
|
+
// Oauth2.1 RFC 3.2.4
|
|
1317
|
+
case 401:
|
|
1318
|
+
return oauth2authorized(req, next);
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
return res;
|
|
1323
|
+
};
|
|
1324
|
+
async function oauth2authorized(req, next) {
|
|
1325
|
+
getTokensFromLocation();
|
|
1326
|
+
let accessToken = options.tokens.get("access_token");
|
|
1327
|
+
if (!accessToken) {
|
|
1328
|
+
try {
|
|
1329
|
+
let token = await fetchAccessToken();
|
|
1330
|
+
if (!token) {
|
|
1331
|
+
return everything_default.response("false");
|
|
1332
|
+
}
|
|
1333
|
+
} catch (e) {
|
|
1334
|
+
throw e;
|
|
1335
|
+
}
|
|
1336
|
+
return oauth2authorized(req, next);
|
|
1337
|
+
} else if (isExpired(accessToken)) {
|
|
1338
|
+
try {
|
|
1339
|
+
let token = await fetchRefreshToken();
|
|
1340
|
+
if (!token) {
|
|
1341
|
+
return everything_default.response("false");
|
|
1342
|
+
}
|
|
1343
|
+
} catch (e) {
|
|
1344
|
+
throw e;
|
|
1345
|
+
}
|
|
1346
|
+
return oauth2authorized(req, next);
|
|
1347
|
+
} else {
|
|
1348
|
+
req = everything_default.request(req, {
|
|
1349
|
+
headers: {
|
|
1350
|
+
Authorization: accessToken.type + " " + accessToken.value
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
return next(req);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function getTokensFromLocation() {
|
|
1357
|
+
if (typeof window !== "undefined" && window?.location) {
|
|
1358
|
+
let url2 = everything_default.url(window.location);
|
|
1359
|
+
let code, state, params2;
|
|
1360
|
+
if (url2.searchParams.has("code")) {
|
|
1361
|
+
params2 = url2.searchParams;
|
|
1362
|
+
url2 = url2.with({ search: "" });
|
|
1363
|
+
history.pushState({}, "", url2.href);
|
|
1364
|
+
} else if (url2.hash) {
|
|
1365
|
+
let query = url2.hash.substr(1);
|
|
1366
|
+
params2 = new URLSearchParams("?" + query);
|
|
1367
|
+
url2 = url2.with({ hash: "" });
|
|
1368
|
+
history.pushState({}, "", url2.href);
|
|
1369
|
+
}
|
|
1370
|
+
if (params2) {
|
|
1371
|
+
code = params2.get("code");
|
|
1372
|
+
state = params2.get("state");
|
|
1373
|
+
let storedState = options.state.get("metro/state");
|
|
1374
|
+
if (!state || state !== storedState) {
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
if (code) {
|
|
1378
|
+
options.tokens.set("authorization_code", code);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
async function fetchAccessToken() {
|
|
1384
|
+
if (oauth22.grant_type === "authorization_code" && !options.tokens.has("authorization_code")) {
|
|
1385
|
+
let authReqURL = await getAuthorizationCodeURL();
|
|
1386
|
+
if (!options.callbacks.authorize || typeof options.callbacks.authorize !== "function") {
|
|
1387
|
+
throw everything_default.metroError("oauth2mw: oauth2 with grant_type:authorization_code requires a callback function in client options.options.callbacks.authorize");
|
|
1388
|
+
}
|
|
1389
|
+
let token = await options.callbacks.authorize(authReqURL);
|
|
1390
|
+
if (token) {
|
|
1391
|
+
options.tokens.set("authorization_code", token);
|
|
1392
|
+
} else {
|
|
1393
|
+
return false;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
let tokenReq = getAccessTokenRequest();
|
|
1397
|
+
let response2 = await options.client.post(tokenReq);
|
|
1398
|
+
if (!response2.ok) {
|
|
1399
|
+
let msg = await response2.text();
|
|
1400
|
+
throw everything_default.metroError("OAuth2mw: fetch access_token: " + response2.status + ": " + response2.statusText, { cause: tokenReq });
|
|
1401
|
+
}
|
|
1402
|
+
let data = await response2.json();
|
|
1403
|
+
options.tokens.set("access_token", {
|
|
1404
|
+
value: data.access_token,
|
|
1405
|
+
expires: getExpires(data.expires_in),
|
|
1406
|
+
type: data.token_type,
|
|
1407
|
+
scope: data.scope
|
|
1408
|
+
});
|
|
1409
|
+
if (data.refresh_token) {
|
|
1410
|
+
let token = {
|
|
1411
|
+
value: data.refresh_token
|
|
1412
|
+
};
|
|
1413
|
+
options.tokens.set("refresh_token", token);
|
|
1414
|
+
}
|
|
1415
|
+
return data;
|
|
1416
|
+
}
|
|
1417
|
+
async function fetchRefreshToken() {
|
|
1418
|
+
let refreshTokenReq = getAccessTokenRequest("refresh_token");
|
|
1419
|
+
let response2 = await options.client.post(refreshTokenReq);
|
|
1420
|
+
if (!response2.ok) {
|
|
1421
|
+
throw everything_default.metroError("OAuth2mw: refresh access_token: " + response2.status + ": " + response2.statusText, { cause: refreshTokenReq });
|
|
1422
|
+
}
|
|
1423
|
+
let data = await response2.json();
|
|
1424
|
+
options.tokens.set("access_token", {
|
|
1425
|
+
value: data.access_token,
|
|
1426
|
+
expires: getExpires(data.expires_in),
|
|
1427
|
+
type: data.token_type,
|
|
1428
|
+
scope: data.scope
|
|
1429
|
+
});
|
|
1430
|
+
if (data.refresh_token) {
|
|
1431
|
+
let token = {
|
|
1432
|
+
value: data.refresh_token
|
|
1433
|
+
};
|
|
1434
|
+
options.tokens.set("refresh_token", token);
|
|
1435
|
+
} else {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return data;
|
|
1439
|
+
}
|
|
1440
|
+
async function getAuthorizationCodeURL() {
|
|
1441
|
+
if (!oauth22.authorization_endpoint) {
|
|
1442
|
+
throw everything_default.metroError("oauth2mw: Missing options.oauth2_configuration.authorization_endpoint");
|
|
1443
|
+
}
|
|
1444
|
+
let url2 = everything_default.url(oauth22.authorization_endpoint, { hash: "" });
|
|
1445
|
+
assert2(oauth22, {
|
|
1446
|
+
client_id: /.+/,
|
|
1447
|
+
redirect_uri: /.+/,
|
|
1448
|
+
scope: /.*/
|
|
1449
|
+
});
|
|
1450
|
+
let search = {
|
|
1451
|
+
response_type: "code",
|
|
1452
|
+
// implicit flow uses 'token' here, but is not considered safe, so not supported
|
|
1453
|
+
client_id: oauth22.client_id,
|
|
1454
|
+
redirect_uri: oauth22.redirect_uri,
|
|
1455
|
+
state: oauth22.state || createState(40)
|
|
1456
|
+
// OAuth2.1 RFC says optional, but its a good idea to always add/check it
|
|
1457
|
+
};
|
|
1458
|
+
if (oauth22.response_type) {
|
|
1459
|
+
search.response_type = oauth22.response_type;
|
|
1460
|
+
}
|
|
1461
|
+
if (oauth22.response_mode) {
|
|
1462
|
+
search.response_mode = oauth22.response_mode;
|
|
1463
|
+
}
|
|
1464
|
+
options.state.set(search.state);
|
|
1465
|
+
if (oauth22.client_secret) {
|
|
1466
|
+
search.client_secret = oauth22.client_secret;
|
|
1467
|
+
}
|
|
1468
|
+
if (oauth22.code_verifier) {
|
|
1469
|
+
search.code_challenge = base64url_encode(await generateCodeChallenge(oauth22.code_verifier));
|
|
1470
|
+
search.code_challenge_method = "S256";
|
|
1471
|
+
}
|
|
1472
|
+
if (oauth22.scope) {
|
|
1473
|
+
search.scope = oauth22.scope;
|
|
1474
|
+
}
|
|
1475
|
+
if (oauth22.prompt) {
|
|
1476
|
+
search.prompt = oauth22.prompt;
|
|
1477
|
+
}
|
|
1478
|
+
return everything_default.url(url2, { search });
|
|
1479
|
+
}
|
|
1480
|
+
function getAccessTokenRequest(grant_type = null) {
|
|
1481
|
+
assert2(oauth22, {
|
|
1482
|
+
client_id: /.+/,
|
|
1483
|
+
redirect_uri: /.+/
|
|
1484
|
+
});
|
|
1485
|
+
if (!oauth22.token_endpoint) {
|
|
1486
|
+
throw everything_default.metroError("oauth2mw: Missing options.endpoints.token url");
|
|
1487
|
+
}
|
|
1488
|
+
let url2 = everything_default.url(oauth22.token_endpoint, { hash: "" });
|
|
1489
|
+
let params2 = {
|
|
1490
|
+
grant_type: grant_type || oauth22.grant_type,
|
|
1491
|
+
client_id: oauth22.client_id
|
|
1492
|
+
};
|
|
1493
|
+
if (oauth22.code_verifier) {
|
|
1494
|
+
params2.code_verifier = base64url_encode(oauth22.code_verifier);
|
|
1495
|
+
}
|
|
1496
|
+
if (oauth22.client_secret) {
|
|
1497
|
+
params2.client_secret = oauth22.client_secret;
|
|
1498
|
+
}
|
|
1499
|
+
if (oauth22.scope) {
|
|
1500
|
+
params2.scope = oauth22.scope;
|
|
1501
|
+
}
|
|
1502
|
+
switch (oauth22.grant_type) {
|
|
1503
|
+
case "authorization_code":
|
|
1504
|
+
params2.redirect_uri = oauth22.redirect_uri;
|
|
1505
|
+
params2.code = options.tokens.get("authorization_code");
|
|
1506
|
+
if (options.dpop) {
|
|
1507
|
+
const keyPair = options.tokens.get("keyPair");
|
|
1508
|
+
params2.dpop_jkt = keyPair.publicKey;
|
|
1509
|
+
}
|
|
1510
|
+
break;
|
|
1511
|
+
case "client_credentials":
|
|
1512
|
+
break;
|
|
1513
|
+
case "refresh_token":
|
|
1514
|
+
params2.refresh_token = oauth22.refresh_token;
|
|
1515
|
+
break;
|
|
1516
|
+
default:
|
|
1517
|
+
throw new Error("Unknown grant_type: ".oauth2.grant_type);
|
|
1518
|
+
break;
|
|
1519
|
+
}
|
|
1520
|
+
return everything_default.request(url2, { method: "POST", body: new URLSearchParams(params2) });
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
function isExpired(token) {
|
|
1524
|
+
if (!token) {
|
|
1525
|
+
return true;
|
|
1526
|
+
}
|
|
1527
|
+
let expires = new Date(token.expires);
|
|
1528
|
+
let now = /* @__PURE__ */ new Date();
|
|
1529
|
+
return now.getTime() > expires.getTime();
|
|
1530
|
+
}
|
|
1531
|
+
function getExpires(duration) {
|
|
1532
|
+
if (duration instanceof Date) {
|
|
1533
|
+
return new Date(duration.getTime());
|
|
1534
|
+
}
|
|
1535
|
+
if (typeof duration === "number") {
|
|
1536
|
+
let date = /* @__PURE__ */ new Date();
|
|
1537
|
+
date.setSeconds(date.getSeconds() + duration);
|
|
1538
|
+
return date;
|
|
1539
|
+
}
|
|
1540
|
+
throw new TypeError("Unknown expires type " + duration);
|
|
1541
|
+
}
|
|
1542
|
+
function generateCodeVerifier(size = 64) {
|
|
1543
|
+
const code_verifier = new Uint8Array(size);
|
|
1544
|
+
globalThis.crypto.getRandomValues(code_verifier);
|
|
1545
|
+
return code_verifier;
|
|
1546
|
+
}
|
|
1547
|
+
async function generateCodeChallenge(code_verifier) {
|
|
1548
|
+
const b64encoded = base64url_encode(code_verifier);
|
|
1549
|
+
const encoder2 = new TextEncoder();
|
|
1550
|
+
const data = encoder2.encode(b64encoded);
|
|
1551
|
+
return await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
1552
|
+
}
|
|
1553
|
+
function base64url_encode(buffer) {
|
|
1554
|
+
const byteString = Array.from(new Uint8Array(buffer), (b) => String.fromCharCode(b)).join("");
|
|
1555
|
+
return btoa(byteString).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1556
|
+
}
|
|
1557
|
+
function createState(length) {
|
|
1558
|
+
const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
1559
|
+
let randomState = "";
|
|
1560
|
+
let counter = 0;
|
|
1561
|
+
while (counter < length) {
|
|
1562
|
+
randomState += validChars.charAt(Math.floor(Math.random() * validChars.length));
|
|
1563
|
+
counter++;
|
|
1564
|
+
}
|
|
1565
|
+
return randomState;
|
|
1566
|
+
}
|
|
1567
|
+
function isRedirected() {
|
|
1568
|
+
let url2 = new URL(document.location.href);
|
|
1569
|
+
if (!url2.searchParams.has("code")) {
|
|
1570
|
+
if (url2.hash) {
|
|
1571
|
+
let query = url2.hash.substr(1);
|
|
1572
|
+
params = new URLSearchParams("?" + query);
|
|
1573
|
+
if (params.has("code")) {
|
|
1574
|
+
return true;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1579
|
+
return true;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
// node_modules/@muze-nl/metro-oauth2/src/oauth2.mockserver.mjs
|
|
1583
|
+
var oauth2_mockserver_exports = {};
|
|
1584
|
+
__export(oauth2_mockserver_exports, {
|
|
1585
|
+
default: () => oauth2mockserver
|
|
1586
|
+
});
|
|
1587
|
+
var baseResponse = {
|
|
1588
|
+
status: 200,
|
|
1589
|
+
statusText: "OK",
|
|
1590
|
+
headers: {
|
|
1591
|
+
"Content-Type": "application/json"
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
var badRequest = (error4) => {
|
|
1595
|
+
return {
|
|
1596
|
+
status: 400,
|
|
1597
|
+
statusText: "Bad Request",
|
|
1598
|
+
headers: {
|
|
1599
|
+
"Content-Type": "application/json"
|
|
1600
|
+
},
|
|
1601
|
+
body: JSON.stringify({
|
|
1602
|
+
error: "invalid_request",
|
|
1603
|
+
error_description: error4
|
|
1604
|
+
})
|
|
1605
|
+
};
|
|
1606
|
+
};
|
|
1607
|
+
var error3;
|
|
1608
|
+
var pkce = {};
|
|
1609
|
+
function oauth2mockserver(options = {}) {
|
|
1610
|
+
const defaultOptions = {
|
|
1611
|
+
"PKCE": false,
|
|
1612
|
+
"DPoP": false
|
|
1613
|
+
};
|
|
1614
|
+
options = Object.assign({}, defaultOptions, options);
|
|
1615
|
+
return async (req, next) => {
|
|
1616
|
+
let url2 = everything_default.url(req.url);
|
|
1617
|
+
switch (url2.pathname) {
|
|
1618
|
+
case "/authorize/":
|
|
1619
|
+
if (error3 = fails2(url2.searchParams, {
|
|
1620
|
+
response_type: "code",
|
|
1621
|
+
client_id: "mockClientId",
|
|
1622
|
+
state: Optional2(/.*/)
|
|
1623
|
+
})) {
|
|
1624
|
+
return everything_default.response(badRequest(error3));
|
|
1625
|
+
}
|
|
1626
|
+
if (url2.searchParams.has("code_challenge")) {
|
|
1627
|
+
if (!url2.searchParams.has("code_challenge_method")) {
|
|
1628
|
+
return everything_default.response(badRequest("missing code_challenge_method"));
|
|
1629
|
+
}
|
|
1630
|
+
pkce.code_challenge = url2.searchParams.get("code_challenge");
|
|
1631
|
+
pkce.code_challenge_method = url2.searchParams.get("code_challenge_method");
|
|
1632
|
+
}
|
|
1633
|
+
return everything_default.response(baseResponse, {
|
|
1634
|
+
body: JSON.stringify({
|
|
1635
|
+
code: "mockAuthorizeToken",
|
|
1636
|
+
state: url2.searchParams.get("state")
|
|
1637
|
+
})
|
|
1638
|
+
});
|
|
1639
|
+
break;
|
|
1640
|
+
case "/token/":
|
|
1641
|
+
if (req.body[Symbol.metroSource] instanceof URLSearchParams) {
|
|
1642
|
+
let body = {};
|
|
1643
|
+
req.body.forEach((value, key) => body[key] = value);
|
|
1644
|
+
req = req.with({ body });
|
|
1645
|
+
}
|
|
1646
|
+
if (error3 = fails2(req, {
|
|
1647
|
+
method: "POST",
|
|
1648
|
+
body: {
|
|
1649
|
+
grant_type: oneOf2("refresh_token", "authorization_code")
|
|
1650
|
+
}
|
|
1651
|
+
})) {
|
|
1652
|
+
return everything_default.response(badRequest(error3));
|
|
1653
|
+
}
|
|
1654
|
+
switch (req.body.grant_type) {
|
|
1655
|
+
case "refresh_token":
|
|
1656
|
+
if (error3 = fails2(req.body, oneOf2({
|
|
1657
|
+
refresh_token: "mockRefreshToken",
|
|
1658
|
+
client_id: "mockClientId",
|
|
1659
|
+
client_secret: "mockClientSecret"
|
|
1660
|
+
}, {
|
|
1661
|
+
refresh_token: "mockRefreshToken",
|
|
1662
|
+
client_id: "mockClientId",
|
|
1663
|
+
code_verifier: /.+/
|
|
1664
|
+
}))) {
|
|
1665
|
+
return everything_default.response(badRequest(error3));
|
|
1666
|
+
}
|
|
1667
|
+
break;
|
|
1668
|
+
case "access_token":
|
|
1669
|
+
if (error3 = fails2(req.body, oneOf2({
|
|
1670
|
+
client_id: "mockClientId",
|
|
1671
|
+
client_secret: "mockClientSecret"
|
|
1672
|
+
}, {
|
|
1673
|
+
client_id: "mockClientId",
|
|
1674
|
+
code_challenge: /.*/,
|
|
1675
|
+
//FIXME: check that this matches code_verifier
|
|
1676
|
+
code_challenge_method: "S256"
|
|
1677
|
+
}))) {
|
|
1678
|
+
return everything_default.response(badRequest(error3));
|
|
1679
|
+
}
|
|
1680
|
+
break;
|
|
1681
|
+
}
|
|
1682
|
+
return everything_default.response(baseResponse, {
|
|
1683
|
+
body: JSON.stringify({
|
|
1684
|
+
access_token: "mockAccessToken",
|
|
1685
|
+
token_type: "mockExample",
|
|
1686
|
+
expires_in: 3600,
|
|
1687
|
+
refresh_token: "mockRefreshToken",
|
|
1688
|
+
example_parameter: "mockExampleValue"
|
|
1689
|
+
})
|
|
1690
|
+
});
|
|
1691
|
+
break;
|
|
1692
|
+
case "/protected/":
|
|
1693
|
+
let auth = req.headers.get("Authorization");
|
|
1694
|
+
let [type, token] = auth ? auth.split(" ") : [];
|
|
1695
|
+
if (!token || token !== "mockAccessToken") {
|
|
1696
|
+
return everything_default.response({
|
|
1697
|
+
status: 401,
|
|
1698
|
+
statusText: "Forbidden",
|
|
1699
|
+
body: "401 Forbidden"
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
return everything_default.response(baseResponse, {
|
|
1703
|
+
body: JSON.stringify({
|
|
1704
|
+
result: "Success"
|
|
1705
|
+
})
|
|
1706
|
+
});
|
|
1707
|
+
break;
|
|
1708
|
+
case "/public/":
|
|
1709
|
+
return everything_default.response(baseResponse, {
|
|
1710
|
+
body: JSON.stringify({
|
|
1711
|
+
result: "Success"
|
|
1712
|
+
})
|
|
1713
|
+
});
|
|
1714
|
+
break;
|
|
1715
|
+
default:
|
|
1716
|
+
return everything_default.response({
|
|
1717
|
+
status: 404,
|
|
1718
|
+
statusText: "not found",
|
|
1719
|
+
body: "404 Not Found " + url2
|
|
1720
|
+
});
|
|
1721
|
+
break;
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// node_modules/@muze-nl/metro-oauth2/src/oauth2.discovery.mjs
|
|
1727
|
+
var oauth2_discovery_exports = {};
|
|
1728
|
+
__export(oauth2_discovery_exports, {
|
|
1729
|
+
default: () => makeClient
|
|
1730
|
+
});
|
|
1731
|
+
var validAlgorithms = [
|
|
1732
|
+
"HS256",
|
|
1733
|
+
"HS384",
|
|
1734
|
+
"HS512",
|
|
1735
|
+
"RS256",
|
|
1736
|
+
"RS384",
|
|
1737
|
+
"RS512",
|
|
1738
|
+
"ES256",
|
|
1739
|
+
"ES384",
|
|
1740
|
+
"ES512"
|
|
1741
|
+
];
|
|
1742
|
+
var validAuthMethods2 = [
|
|
1743
|
+
"client_secret_post",
|
|
1744
|
+
"client_secret_base",
|
|
1745
|
+
"client_secret_jwt",
|
|
1746
|
+
"private_key_jwt"
|
|
1747
|
+
];
|
|
1748
|
+
var oauth_authorization_server_metadata = {
|
|
1749
|
+
issuer: Required2(validURL2),
|
|
1750
|
+
authorization_endpoint: Required2(validURL2),
|
|
1751
|
+
token_endpoint: Required2(validURL2),
|
|
1752
|
+
jwks_uri: Optional2(validURL2),
|
|
1753
|
+
registration_endpoint: Optional2(validURL2),
|
|
1754
|
+
scopes_supported: Recommended2([]),
|
|
1755
|
+
response_types_supported: Required2(anyOf2("code", "token")),
|
|
1756
|
+
response_modes_supported: Optional2([]),
|
|
1757
|
+
grant_types_supported: Optional2([]),
|
|
1758
|
+
token_endpoint_auth_methods_supported: Optional2([]),
|
|
1759
|
+
token_endpoint_auth_signing_alg_values_supported: Optional2([]),
|
|
1760
|
+
service_documentation: Optional2(validURL2),
|
|
1761
|
+
ui_locales_supported: Optional2([]),
|
|
1762
|
+
op_policy_uri: Optional2(validURL2),
|
|
1763
|
+
op_tos_uri: Optional2(validURL2),
|
|
1764
|
+
revocation_endpoint: Optional2(validURL2),
|
|
1765
|
+
revocation_endpoint_auth_methods_supported: Optional2(validAuthMethods2),
|
|
1766
|
+
revocation_endpoint_auth_signing_alg_values_supported: Optional2(validAlgorithms),
|
|
1767
|
+
introspection_endpoint: Optional2(validURL2),
|
|
1768
|
+
introspection_endpoint_auth_methods_supported: Optional2(validAuthMethods2),
|
|
1769
|
+
introspection_endpoint_auth_signing_alg_values_supported: Optional2(validAlgorithms),
|
|
1770
|
+
code_challendge_methods_supported: Optional2([])
|
|
1771
|
+
};
|
|
1772
|
+
function makeClient(options = {}) {
|
|
1773
|
+
const defaultOptions = {
|
|
1774
|
+
client: everything_default.client()
|
|
1775
|
+
};
|
|
1776
|
+
options = Object.assign({}, defaultOptions, options);
|
|
1777
|
+
assert2(options, {
|
|
1778
|
+
issuer: Required2(validURL2)
|
|
1779
|
+
});
|
|
1780
|
+
const oauth_authorization_server_configuration = fetchWellknownOauthAuthorizationServer(options.issuer);
|
|
1781
|
+
let client2 = options.client.with(options.issuer);
|
|
1782
|
+
}
|
|
1783
|
+
async function fetchWellknownOauthAuthorizationServer(issuer, client2) {
|
|
1784
|
+
let res = client2.get(everything_default.url(issuer, ".wellknown/oauth_authorization_server"));
|
|
1785
|
+
if (res.ok) {
|
|
1786
|
+
assert2(res.headers.get("Content-Type"), /application\/json.*/);
|
|
1787
|
+
let configuration = await res.json();
|
|
1788
|
+
assert2(configuration, oauth_authorization_server_metadata);
|
|
1789
|
+
return configuration;
|
|
1790
|
+
}
|
|
1791
|
+
throw everything_default.metroError("metro.oidcmw: Error while fetching " + issuer + ".wellknown/oauth_authorization_server", res);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
// node_modules/@muze-nl/metro-oauth2/src/keysstore.mjs
|
|
1795
|
+
function keysStore() {
|
|
1796
|
+
return new Promise((resolve, reject) => {
|
|
1797
|
+
const request2 = globalThis.indexedDB.open("metro", 1);
|
|
1798
|
+
request2.onupgradeneeded = () => request2.result.createObjectStore("keyPairs", { keyPath: "domain" });
|
|
1799
|
+
request2.onerror = (event) => {
|
|
1800
|
+
reject(event);
|
|
1801
|
+
};
|
|
1802
|
+
request2.onsuccess = (event) => {
|
|
1803
|
+
const db = event.target.result;
|
|
1804
|
+
resolve({
|
|
1805
|
+
set: function(value, key) {
|
|
1806
|
+
return new Promise((resolve2, reject2) => {
|
|
1807
|
+
const tx = db.transaction("keyPairs", "readwrite", { durability: "strict" });
|
|
1808
|
+
const objectStore = tx.objectStore("keyPairs");
|
|
1809
|
+
tx.oncomplete = () => {
|
|
1810
|
+
resolve2();
|
|
1811
|
+
};
|
|
1812
|
+
tx.onerror = reject2;
|
|
1813
|
+
objectStore.put(value, key);
|
|
1814
|
+
});
|
|
1815
|
+
},
|
|
1816
|
+
get: function(key) {
|
|
1817
|
+
return new Promise((resolve2, reject2) => {
|
|
1818
|
+
const tx = db.transaction("keyPairs", "readonly");
|
|
1819
|
+
const objectStore = tx.objectStore("keyPairs");
|
|
1820
|
+
const request3 = objectStore.get(key);
|
|
1821
|
+
request3.onsuccess = () => {
|
|
1822
|
+
resolve2(request3.result);
|
|
1823
|
+
};
|
|
1824
|
+
request3.onerror = reject2;
|
|
1825
|
+
tx.onerror = reject2;
|
|
1826
|
+
});
|
|
1827
|
+
},
|
|
1828
|
+
clear: function() {
|
|
1829
|
+
return new Promise((resolve2, reject2) => {
|
|
1830
|
+
const tx = db.transaction("keyPairs", "readwrite");
|
|
1831
|
+
const objectStore = tx.objectStore("keyPairs");
|
|
1832
|
+
const request3 = objectStore.clear();
|
|
1833
|
+
request3.onsuccess = () => {
|
|
1834
|
+
resolve2();
|
|
1835
|
+
};
|
|
1836
|
+
request3.onerror = reject2;
|
|
1837
|
+
tx.onerror = reject2;
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
};
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// node_modules/dpop/build/index.js
|
|
1846
|
+
var encoder = new TextEncoder();
|
|
1847
|
+
var decoder = new TextDecoder();
|
|
1848
|
+
function buf(input) {
|
|
1849
|
+
if (typeof input === "string") {
|
|
1850
|
+
return encoder.encode(input);
|
|
1851
|
+
}
|
|
1852
|
+
return decoder.decode(input);
|
|
1853
|
+
}
|
|
1854
|
+
function checkRsaKeyAlgorithm(algorithm) {
|
|
1855
|
+
if (typeof algorithm.modulusLength !== "number" || algorithm.modulusLength < 2048) {
|
|
1856
|
+
throw new OperationProcessingError(`${algorithm.name} modulusLength must be at least 2048 bits`);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
function subtleAlgorithm(key) {
|
|
1860
|
+
switch (key.algorithm.name) {
|
|
1861
|
+
case "ECDSA":
|
|
1862
|
+
return { name: key.algorithm.name, hash: "SHA-256" };
|
|
1863
|
+
case "RSA-PSS":
|
|
1864
|
+
checkRsaKeyAlgorithm(key.algorithm);
|
|
1865
|
+
return {
|
|
1866
|
+
name: key.algorithm.name,
|
|
1867
|
+
saltLength: 256 >> 3
|
|
1868
|
+
};
|
|
1869
|
+
case "RSASSA-PKCS1-v1_5":
|
|
1870
|
+
checkRsaKeyAlgorithm(key.algorithm);
|
|
1871
|
+
return { name: key.algorithm.name };
|
|
1872
|
+
case "Ed25519":
|
|
1873
|
+
return { name: key.algorithm.name };
|
|
1874
|
+
}
|
|
1875
|
+
throw new UnsupportedOperationError();
|
|
1876
|
+
}
|
|
1877
|
+
async function jwt(header, claimsSet, key) {
|
|
1878
|
+
if (key.usages.includes("sign") === false) {
|
|
1879
|
+
throw new TypeError('private CryptoKey instances used for signing assertions must include "sign" in their "usages"');
|
|
1880
|
+
}
|
|
1881
|
+
const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(claimsSet)))}`;
|
|
1882
|
+
const signature = b64u(await crypto.subtle.sign(subtleAlgorithm(key), key, buf(input)));
|
|
1883
|
+
return `${input}.${signature}`;
|
|
1884
|
+
}
|
|
1885
|
+
var CHUNK_SIZE = 32768;
|
|
1886
|
+
function encodeBase64Url(input) {
|
|
1887
|
+
if (input instanceof ArrayBuffer) {
|
|
1888
|
+
input = new Uint8Array(input);
|
|
1889
|
+
}
|
|
1890
|
+
const arr = [];
|
|
1891
|
+
for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {
|
|
1892
|
+
arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
1893
|
+
}
|
|
1894
|
+
return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1895
|
+
}
|
|
1896
|
+
function b64u(input) {
|
|
1897
|
+
return encodeBase64Url(input);
|
|
1898
|
+
}
|
|
1899
|
+
function randomBytes() {
|
|
1900
|
+
return b64u(crypto.getRandomValues(new Uint8Array(32)));
|
|
1901
|
+
}
|
|
1902
|
+
var UnsupportedOperationError = class extends Error {
|
|
1903
|
+
constructor(message) {
|
|
1904
|
+
super(message ?? "operation not supported");
|
|
1905
|
+
this.name = this.constructor.name;
|
|
1906
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
var OperationProcessingError = class extends Error {
|
|
1910
|
+
constructor(message) {
|
|
1911
|
+
super(message);
|
|
1912
|
+
this.name = this.constructor.name;
|
|
1913
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
function psAlg(key) {
|
|
1917
|
+
switch (key.algorithm.hash.name) {
|
|
1918
|
+
case "SHA-256":
|
|
1919
|
+
return "PS256";
|
|
1920
|
+
default:
|
|
1921
|
+
throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
function rsAlg(key) {
|
|
1925
|
+
switch (key.algorithm.hash.name) {
|
|
1926
|
+
case "SHA-256":
|
|
1927
|
+
return "RS256";
|
|
1928
|
+
default:
|
|
1929
|
+
throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name");
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
function esAlg(key) {
|
|
1933
|
+
switch (key.algorithm.namedCurve) {
|
|
1934
|
+
case "P-256":
|
|
1935
|
+
return "ES256";
|
|
1936
|
+
default:
|
|
1937
|
+
throw new UnsupportedOperationError("unsupported EcKeyAlgorithm namedCurve");
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
function determineJWSAlgorithm(key) {
|
|
1941
|
+
switch (key.algorithm.name) {
|
|
1942
|
+
case "RSA-PSS":
|
|
1943
|
+
return psAlg(key);
|
|
1944
|
+
case "RSASSA-PKCS1-v1_5":
|
|
1945
|
+
return rsAlg(key);
|
|
1946
|
+
case "ECDSA":
|
|
1947
|
+
return esAlg(key);
|
|
1948
|
+
case "Ed25519":
|
|
1949
|
+
return "EdDSA";
|
|
1950
|
+
default:
|
|
1951
|
+
throw new UnsupportedOperationError("unsupported CryptoKey algorithm name");
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
function isCryptoKey(key) {
|
|
1955
|
+
return key instanceof CryptoKey;
|
|
1956
|
+
}
|
|
1957
|
+
function isPrivateKey(key) {
|
|
1958
|
+
return isCryptoKey(key) && key.type === "private";
|
|
1959
|
+
}
|
|
1960
|
+
function isPublicKey(key) {
|
|
1961
|
+
return isCryptoKey(key) && key.type === "public";
|
|
1962
|
+
}
|
|
1963
|
+
function epochTime() {
|
|
1964
|
+
return Math.floor(Date.now() / 1e3);
|
|
1965
|
+
}
|
|
1966
|
+
async function DPoP(keypair, htu, htm, nonce, accessToken, additional) {
|
|
1967
|
+
const privateKey = keypair?.privateKey;
|
|
1968
|
+
const publicKey = keypair?.publicKey;
|
|
1969
|
+
if (!isPrivateKey(privateKey)) {
|
|
1970
|
+
throw new TypeError('"keypair.privateKey" must be a private CryptoKey');
|
|
1971
|
+
}
|
|
1972
|
+
if (!isPublicKey(publicKey)) {
|
|
1973
|
+
throw new TypeError('"keypair.publicKey" must be a public CryptoKey');
|
|
1974
|
+
}
|
|
1975
|
+
if (publicKey.extractable !== true) {
|
|
1976
|
+
throw new TypeError('"keypair.publicKey.extractable" must be true');
|
|
1977
|
+
}
|
|
1978
|
+
if (typeof htu !== "string") {
|
|
1979
|
+
throw new TypeError('"htu" must be a string');
|
|
1980
|
+
}
|
|
1981
|
+
if (typeof htm !== "string") {
|
|
1982
|
+
throw new TypeError('"htm" must be a string');
|
|
1983
|
+
}
|
|
1984
|
+
if (nonce !== void 0 && typeof nonce !== "string") {
|
|
1985
|
+
throw new TypeError('"nonce" must be a string or undefined');
|
|
1986
|
+
}
|
|
1987
|
+
if (accessToken !== void 0 && typeof accessToken !== "string") {
|
|
1988
|
+
throw new TypeError('"accessToken" must be a string or undefined');
|
|
1989
|
+
}
|
|
1990
|
+
if (additional !== void 0 && (typeof additional !== "object" || additional === null || Array.isArray(additional))) {
|
|
1991
|
+
throw new TypeError('"additional" must be an object');
|
|
1992
|
+
}
|
|
1993
|
+
return jwt({
|
|
1994
|
+
alg: determineJWSAlgorithm(privateKey),
|
|
1995
|
+
typ: "dpop+jwt",
|
|
1996
|
+
jwk: await publicJwk(publicKey)
|
|
1997
|
+
}, {
|
|
1998
|
+
...additional,
|
|
1999
|
+
iat: epochTime(),
|
|
2000
|
+
jti: randomBytes(),
|
|
2001
|
+
htm,
|
|
2002
|
+
nonce,
|
|
2003
|
+
htu,
|
|
2004
|
+
ath: accessToken ? b64u(await crypto.subtle.digest("SHA-256", buf(accessToken))) : void 0
|
|
2005
|
+
}, privateKey);
|
|
2006
|
+
}
|
|
2007
|
+
async function publicJwk(key) {
|
|
2008
|
+
const { kty, e, n, x, y, crv } = await crypto.subtle.exportKey("jwk", key);
|
|
2009
|
+
return { kty, crv, e, n, x, y };
|
|
2010
|
+
}
|
|
2011
|
+
async function generateKeyPair(alg, options) {
|
|
2012
|
+
let algorithm;
|
|
2013
|
+
if (typeof alg !== "string" || alg.length === 0) {
|
|
2014
|
+
throw new TypeError('"alg" must be a non-empty string');
|
|
2015
|
+
}
|
|
2016
|
+
switch (alg) {
|
|
2017
|
+
case "PS256":
|
|
2018
|
+
algorithm = {
|
|
2019
|
+
name: "RSA-PSS",
|
|
2020
|
+
hash: "SHA-256",
|
|
2021
|
+
modulusLength: options?.modulusLength ?? 2048,
|
|
2022
|
+
publicExponent: new Uint8Array([1, 0, 1])
|
|
2023
|
+
};
|
|
2024
|
+
break;
|
|
2025
|
+
case "RS256":
|
|
2026
|
+
algorithm = {
|
|
2027
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
2028
|
+
hash: "SHA-256",
|
|
2029
|
+
modulusLength: options?.modulusLength ?? 2048,
|
|
2030
|
+
publicExponent: new Uint8Array([1, 0, 1])
|
|
2031
|
+
};
|
|
2032
|
+
break;
|
|
2033
|
+
case "ES256":
|
|
2034
|
+
algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
2035
|
+
break;
|
|
2036
|
+
case "EdDSA":
|
|
2037
|
+
algorithm = { name: "Ed25519" };
|
|
2038
|
+
break;
|
|
2039
|
+
default:
|
|
2040
|
+
throw new UnsupportedOperationError();
|
|
2041
|
+
}
|
|
2042
|
+
return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, ["sign", "verify"]);
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
// node_modules/@muze-nl/metro-oauth2/src/oauth2.dpop.mjs
|
|
2046
|
+
function dpopmw(options) {
|
|
2047
|
+
assert2(options, {
|
|
2048
|
+
site: Required2(validURL2),
|
|
2049
|
+
authorization_endpoint: Required2(validURL2),
|
|
2050
|
+
token_endpoint: Required2(validURL2)
|
|
2051
|
+
// dpop_signing_alg_values_supported: Required([]) // this property is unfortunately rarely supported
|
|
2052
|
+
});
|
|
2053
|
+
return async (req, next) => {
|
|
2054
|
+
const keys = await keysStore();
|
|
2055
|
+
let keyInfo = await keys.get(options.site);
|
|
2056
|
+
if (!keyInfo) {
|
|
2057
|
+
let keyPair = await generateKeyPair("ES256");
|
|
2058
|
+
keyInfo = { domain: options.site, keyPair };
|
|
2059
|
+
await keys.set(keyInfo);
|
|
2060
|
+
}
|
|
2061
|
+
const url2 = everything_default.url(req.url);
|
|
2062
|
+
if (req.url.startsWith(options.authorization_endpoint) || req.url.startsWith(options.token_endpoint)) {
|
|
2063
|
+
const dpopHeader = await DPoP(keyInfo.keyPair, req.url, req.method);
|
|
2064
|
+
req = req.with({
|
|
2065
|
+
headers: {
|
|
2066
|
+
"DPoP": dpopHeader
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
} else if (req.headers.has("Authorization")) {
|
|
2070
|
+
const nonce = localStorage.getItem(url2.host + ":nonce") || void 0;
|
|
2071
|
+
const accessToken = req.headers.get("Authorization").split(" ")[1];
|
|
2072
|
+
const dpopHeader = await DPoP(keyInfo.keyPair, req.url, req.method, nonce, accessToken);
|
|
2073
|
+
req = req.with({
|
|
2074
|
+
headers: {
|
|
2075
|
+
"Authorization": "DPoP " + accessToken,
|
|
2076
|
+
//solidcommunity server sends accesstoken with type Bearer
|
|
2077
|
+
"DPoP": dpopHeader
|
|
2078
|
+
}
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
let response2 = await next(req);
|
|
2082
|
+
if (response2.headers.get("DPoP-Nonce")) {
|
|
2083
|
+
localStorage.setItem(url2.host + ":nonce", response2.headers.get("DPoP-Nonce"));
|
|
2084
|
+
}
|
|
2085
|
+
return response2;
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// node_modules/@muze-nl/metro-oauth2/src/browser.mjs
|
|
2090
|
+
var oauth2 = Object.assign(oauth2mw, oauth2_exports, {
|
|
2091
|
+
mockserver: oauth2_mockserver_exports,
|
|
2092
|
+
discovery: oauth2_discovery_exports,
|
|
2093
|
+
tokenstore: tokenStore,
|
|
2094
|
+
dpopmw,
|
|
2095
|
+
keysstore: keysStore
|
|
2096
|
+
});
|
|
2097
|
+
globalThis.oauth2 = oauth2;
|
|
2098
|
+
var browser_default = oauth2;
|
|
2099
|
+
|
|
2100
|
+
// src/oidc.store.mjs
|
|
2101
|
+
function oidcStore(site) {
|
|
2102
|
+
let store;
|
|
2103
|
+
if (typeof localStorage !== "undefined") {
|
|
2104
|
+
store = {
|
|
2105
|
+
get: (name) => JSON.parse(localStorage.getItem("metro/oidc:" + site + ":" + name)),
|
|
2106
|
+
set: (name, value) => localStorage.setItem("metro/oidc:" + site + ":" + name, JSON.stringify(value)),
|
|
2107
|
+
has: (name) => localStorage.getItem("metro/oidc:" + site + ":" + name) !== null
|
|
2108
|
+
};
|
|
2109
|
+
} else {
|
|
2110
|
+
let storeMap = /* @__PURE__ */ new Map();
|
|
2111
|
+
store = {
|
|
2112
|
+
get: (name) => JSON.parse(storeMap.get("metro/oidc:" + site + ":" + name) || null),
|
|
2113
|
+
set: (name, value) => storeMap.set("metro/oidc:" + site + ":" + name, JSON.stringify(value)),
|
|
2114
|
+
has: (name) => storeMap.has("metro/oidc:" + site + ":" + name)
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
return store;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
// src/oidcmw.mjs
|
|
2121
|
+
function oidcmw(options = {}) {
|
|
2122
|
+
const defaultOptions = {
|
|
2123
|
+
client: everything_default.client(),
|
|
2124
|
+
force_authorization: false
|
|
2125
|
+
};
|
|
2126
|
+
options = Object.assign({}, defaultOptions, options);
|
|
2127
|
+
assert(options, {
|
|
2128
|
+
client: Required(instanceOf(everything_default.client().constructor)),
|
|
2129
|
+
// required because it is set in defaultOptions
|
|
2130
|
+
client_info: Required(),
|
|
2131
|
+
issuer: Required(validURL),
|
|
2132
|
+
oauth2: Optional({}),
|
|
2133
|
+
openid_configuration: Optional()
|
|
2134
|
+
});
|
|
2135
|
+
if (!options.store) {
|
|
2136
|
+
options.store = oidcStore(options.issuer);
|
|
2137
|
+
}
|
|
2138
|
+
if (!options.openid_configuration && options.store.has("openid_configuration")) {
|
|
2139
|
+
options.openid_configuration = options.store.get("openid_configuration");
|
|
2140
|
+
}
|
|
2141
|
+
if (!options.client_info.client_id && options.store.has("client_info")) {
|
|
2142
|
+
options.client_info = options.store.get("client_info");
|
|
2143
|
+
}
|
|
2144
|
+
return async (req, next) => {
|
|
2145
|
+
let res;
|
|
2146
|
+
if (!options.force_authorization) {
|
|
2147
|
+
try {
|
|
2148
|
+
res = await next(req);
|
|
2149
|
+
} catch (err) {
|
|
2150
|
+
if (res.status != 401 && res.status != 403) {
|
|
2151
|
+
throw err;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
if (res.ok || res.status != 401 && res.status != 403) {
|
|
2155
|
+
return res;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
if (!options.openid_configuration) {
|
|
2159
|
+
options.openid_configuration = await oidcDiscovery({
|
|
2160
|
+
issuer: options.issuer
|
|
2161
|
+
});
|
|
2162
|
+
options.store.set("openid_configuration", options.openid_configuration);
|
|
2163
|
+
}
|
|
2164
|
+
if (!options.client_info?.client_id) {
|
|
2165
|
+
assert(options.client_info?.client_name, Required());
|
|
2166
|
+
if (!options.openid_configuration.registration_endpoint) {
|
|
2167
|
+
throw everything_default.metroError("metro.oidcmw: Error: issuer " + options.issuer + " does not support dynamic client registration, but you haven't specified a client_id");
|
|
2168
|
+
}
|
|
2169
|
+
options.client_info = await register({
|
|
2170
|
+
registration_endpoint: options.openid_configuration.registration_endpoint,
|
|
2171
|
+
client_info: options.client_info
|
|
2172
|
+
});
|
|
2173
|
+
options.store.set("client_info", options.client_info);
|
|
2174
|
+
}
|
|
2175
|
+
const scope = options.scope || "openid";
|
|
2176
|
+
const oauth2Options = Object.assign(
|
|
2177
|
+
{
|
|
2178
|
+
site: options.issuer,
|
|
2179
|
+
client: options.client,
|
|
2180
|
+
force_authorization: true,
|
|
2181
|
+
oauth2_configuration: {
|
|
2182
|
+
client_id: options.client_info.client_id,
|
|
2183
|
+
client_secret: options.client_info.client_secret,
|
|
2184
|
+
grant_type: "authorization_code",
|
|
2185
|
+
response_type: "code",
|
|
2186
|
+
response_mode: "query",
|
|
2187
|
+
authorization_endpoint: options.openid_configuration.authorization_endpoint,
|
|
2188
|
+
token_endpoint: options.openid_configuration.token_endpoint,
|
|
2189
|
+
scope,
|
|
2190
|
+
//FIXME: should only use scopes supported by server
|
|
2191
|
+
redirect_uri: options.client_info.redirect_uris[0]
|
|
2192
|
+
//FIXME: find the best match?
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
//...
|
|
2196
|
+
);
|
|
2197
|
+
const dpopOptions = {
|
|
2198
|
+
site: options.issuer,
|
|
2199
|
+
authorization_endpoint: options.openid_configuration.authorization_endpoint,
|
|
2200
|
+
token_endpoint: options.openid_configuration.token_endpoint,
|
|
2201
|
+
dpop_signing_alg_values_supported: options.openid_configuration.dpop_signing_alg_values_supported
|
|
2202
|
+
};
|
|
2203
|
+
const storeIdToken = async (req2, next2) => {
|
|
2204
|
+
const res2 = await next2(req2);
|
|
2205
|
+
const contentType = res2.headers.get("content-type");
|
|
2206
|
+
if (contentType?.startsWith("application/json")) {
|
|
2207
|
+
const res22 = res2.clone();
|
|
2208
|
+
try {
|
|
2209
|
+
let data = await res22.json();
|
|
2210
|
+
if (data && data.id_token) {
|
|
2211
|
+
options.store.set("id_token", data.id_token);
|
|
2212
|
+
}
|
|
2213
|
+
} catch (e) {
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
return res2;
|
|
2217
|
+
};
|
|
2218
|
+
const dPopClient = options.client.with(options.issuer).with(storeIdToken).with(browser_default.dpopmw(dpopOptions));
|
|
2219
|
+
oauth2Options.client = dPopClient;
|
|
2220
|
+
const oauth2client = dPopClient.with(browser_default(oauth2Options));
|
|
2221
|
+
res = await oauth2client.fetch(req);
|
|
2222
|
+
return res;
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
function isRedirected2() {
|
|
2226
|
+
return browser_default.isRedirected();
|
|
2227
|
+
}
|
|
2228
|
+
function idToken(options) {
|
|
2229
|
+
return options.store.get("id_token");
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
// src/browser.mjs
|
|
2233
|
+
var oidc = Object.assign(oidcmw, {
|
|
2234
|
+
discover: oidcDiscovery,
|
|
2235
|
+
register,
|
|
2236
|
+
isRedirected: isRedirected2,
|
|
2237
|
+
idToken
|
|
2238
|
+
});
|
|
2239
|
+
globalThis.oidc = oidc;
|
|
2240
|
+
})();
|
|
2
2241
|
//# sourceMappingURL=browser.js.map
|