UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

1,210 lines 125 kB
import { $context, $hook, $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive, z } from "alepha"; import { $cookie, AlephaServerCookies, ServerCookiesProvider } from "alepha/server/cookies"; import { DateTimeProvider } from "alepha/datetime"; import { InvalidCredentialsError, SecurityError, SecurityProvider, userAccountInfoSchema } from "alepha/security"; import { $logger } from "alepha/logger"; import { $route, BadRequestError } from "alepha/server"; import { ServerLinksProvider, apiRegistryResponseSchema } from "alepha/server/links"; //#region ../../../../node_modules/oauth4webapi/build/index.js let USER_AGENT$1; if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) USER_AGENT$1 = `oauth4webapi/v3.8.5`; function looseInstanceOf(input, expected) { if (input == null) return false; try { return input instanceof expected || Object.getPrototypeOf(input)[Symbol.toStringTag] === expected.prototype[Symbol.toStringTag]; } catch { return false; } } const ERR_INVALID_ARG_VALUE$1 = "ERR_INVALID_ARG_VALUE"; const ERR_INVALID_ARG_TYPE$1 = "ERR_INVALID_ARG_TYPE"; function CodedTypeError$1(message, code, cause) { const err = new TypeError(message, { cause }); Object.assign(err, { code }); return err; } const allowInsecureRequests$1 = Symbol(); const clockSkew = Symbol(); const clockTolerance = Symbol(); const customFetch$1 = Symbol(); const jweDecrypt = Symbol(); const encoder$1 = new TextEncoder(); const decoder$2 = new TextDecoder(); function buf(input) { if (typeof input === "string") return encoder$1.encode(input); return decoder$2.decode(input); } let encodeBase64Url; if (Uint8Array.prototype.toBase64) encodeBase64Url = (input) => { if (input instanceof ArrayBuffer) input = new Uint8Array(input); return input.toBase64({ alphabet: "base64url", omitPadding: true }); }; else { const CHUNK_SIZE = 32768; encodeBase64Url = (input) => { if (input instanceof ArrayBuffer) input = new Uint8Array(input); const arr = []; for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE))); return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); }; } let decodeBase64Url; if (Uint8Array.fromBase64) decodeBase64Url = (input) => { try { return Uint8Array.fromBase64(input, { alphabet: "base64url" }); } catch (cause) { throw CodedTypeError$1("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE$1, cause); } }; else decodeBase64Url = (input) => { try { const binary = atob(input.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "")); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i); return bytes; } catch (cause) { throw CodedTypeError$1("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE$1, cause); } }; function b64u(input) { if (typeof input === "string") return decodeBase64Url(input); return encodeBase64Url(input); } var UnsupportedOperationError = class extends Error { code; constructor(message, options) { super(message, options); this.name = this.constructor.name; this.code = UNSUPPORTED_OPERATION; Error.captureStackTrace?.(this, this.constructor); } }; var OperationProcessingError = class extends Error { code; constructor(message, options) { super(message, options); this.name = this.constructor.name; if (options?.code) this.code = options?.code; Error.captureStackTrace?.(this, this.constructor); } }; function OPE(message, code, cause) { return new OperationProcessingError(message, { code, cause }); } function isJsonObject(input) { if (input === null || typeof input !== "object" || Array.isArray(input)) return false; return true; } function prepareHeaders(input) { if (looseInstanceOf(input, Headers)) input = Object.fromEntries(input.entries()); const headers = new Headers(input ?? {}); if (USER_AGENT$1 && !headers.has("user-agent")) headers.set("user-agent", USER_AGENT$1); if (headers.has("authorization")) throw CodedTypeError$1("\"options.headers\" must not include the \"authorization\" header name", ERR_INVALID_ARG_VALUE$1); return headers; } function signal$1(url, value) { if (value !== void 0) { if (typeof value === "function") value = value(url.href); if (!(value instanceof AbortSignal)) throw CodedTypeError$1("\"options.signal\" must return or be an instance of AbortSignal", ERR_INVALID_ARG_TYPE$1); return value; } } function replaceDoubleSlash(pathname) { if (pathname.includes("//")) return pathname.replace("//", "/"); return pathname; } function prependWellKnown(url, wellKnown, allowTerminatingSlash = false) { if (url.pathname === "/") url.pathname = wellKnown; else url.pathname = replaceDoubleSlash(`${wellKnown}/${allowTerminatingSlash ? url.pathname : url.pathname.replace(/(\/)$/, "")}`); return url; } function appendWellKnown(url, wellKnown) { url.pathname = replaceDoubleSlash(`${url.pathname}/${wellKnown}`); return url; } async function performDiscovery$1(input, urlName, transform, options) { if (!(input instanceof URL)) throw CodedTypeError$1(`"${urlName}" must be an instance of URL`, ERR_INVALID_ARG_TYPE$1); checkProtocol(input, options?.[allowInsecureRequests$1] !== true); const url = transform(new URL(input.href)); const headers = prepareHeaders(options?.headers); headers.set("accept", "application/json"); return (options?.[customFetch$1] || fetch)(url.href, { body: void 0, headers: Object.fromEntries(headers.entries()), method: "GET", redirect: "manual", signal: signal$1(url, options?.signal) }); } async function discoveryRequest(issuerIdentifier, options) { return performDiscovery$1(issuerIdentifier, "issuerIdentifier", (url) => { switch (options?.algorithm) { case void 0: case "oidc": appendWellKnown(url, ".well-known/openid-configuration"); break; case "oauth2": prependWellKnown(url, ".well-known/oauth-authorization-server"); break; default: throw CodedTypeError$1("\"options.algorithm\" must be \"oidc\" (default), or \"oauth2\"", ERR_INVALID_ARG_VALUE$1); } return url; }, options); } function assertNumber(input, allow0, it, code, cause) { try { if (typeof input !== "number" || !Number.isFinite(input)) throw CodedTypeError$1(`${it} must be a number`, ERR_INVALID_ARG_TYPE$1, cause); if (input > 0) return; if (allow0) { if (input !== 0) throw CodedTypeError$1(`${it} must be a non-negative number`, ERR_INVALID_ARG_VALUE$1, cause); return; } throw CodedTypeError$1(`${it} must be a positive number`, ERR_INVALID_ARG_VALUE$1, cause); } catch (err) { if (code) throw OPE(err.message, code, cause); throw err; } } function assertString$1(input, it, code, cause) { try { if (typeof input !== "string") throw CodedTypeError$1(`${it} must be a string`, ERR_INVALID_ARG_TYPE$1, cause); if (input.length === 0) throw CodedTypeError$1(`${it} must not be empty`, ERR_INVALID_ARG_VALUE$1, cause); } catch (err) { if (code) throw OPE(err.message, code, cause); throw err; } } async function processDiscoveryResponse(expectedIssuerIdentifier, response) { const expected = expectedIssuerIdentifier; if (!(expected instanceof URL) && expected !== _nodiscoverycheck) throw CodedTypeError$1("\"expectedIssuerIdentifier\" must be an instance of URL", ERR_INVALID_ARG_TYPE$1); if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1); if (response.status !== 200) throw OPE("\"response\" is not a conform Authorization Server Metadata response (unexpected HTTP status code)", RESPONSE_IS_NOT_CONFORM, response); assertReadableResponse(response); const json = await getResponseJsonBody(response); assertString$1(json.issuer, "\"response\" body \"issuer\" property", INVALID_RESPONSE, { body: json }); if (expected !== _nodiscoverycheck && new URL(json.issuer).href !== expected.href) throw OPE("\"response\" body \"issuer\" property does not match the expected value", JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: "issuer" }); return json; } function assertApplicationJson(response) { assertContentType(response, "application/json"); } function notJson(response, ...types) { let msg = "\"response\" content-type must be "; if (types.length > 2) { const last = types.pop(); msg += `${types.join(", ")}, or ${last}`; } else if (types.length === 2) msg += `${types[0]} or ${types[1]}`; else msg += types[0]; return OPE(msg, RESPONSE_IS_NOT_JSON, response); } function assertContentType(response, contentType) { if (getContentType(response) !== contentType) throw notJson(response, contentType); } function randomBytes() { return b64u(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32))); } function generateRandomCodeVerifier() { return randomBytes(); } function generateRandomState() { return randomBytes(); } async function calculatePKCECodeChallenge$1(codeVerifier) { assertString$1(codeVerifier, "codeVerifier"); return b64u(await crypto.subtle.digest("SHA-256", buf(codeVerifier))); } function getClockSkew(client) { const skew = client?.[clockSkew]; return typeof skew === "number" && Number.isFinite(skew) ? skew : 0; } function getClockTolerance(client) { const tolerance = client?.[clockTolerance]; return typeof tolerance === "number" && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1 ? tolerance : 30; } function epochTime() { return Math.floor(Date.now() / 1e3); } function assertAs(as) { if (typeof as !== "object" || as === null) throw CodedTypeError$1("\"as\" must be an object", ERR_INVALID_ARG_TYPE$1); assertString$1(as.issuer, "\"as.issuer\""); } function assertClient(client) { if (typeof client !== "object" || client === null) throw CodedTypeError$1("\"client\" must be an object", ERR_INVALID_ARG_TYPE$1); assertString$1(client.client_id, "\"client.client_id\""); } function ClientSecretPost$1(clientSecret) { assertString$1(clientSecret, "\"clientSecret\""); return (_as, client, body, _headers) => { body.set("client_id", client.client_id); body.set("client_secret", clientSecret); }; } function None$1() { return (_as, client, body, _headers) => { body.set("client_id", client.client_id); }; } const URLParse = URL.parse ? (url, base) => URL.parse(url, base) : (url, base) => { try { return new URL(url, base); } catch { return null; } }; function checkProtocol(url, enforceHttps) { if (enforceHttps && url.protocol !== "https:") throw OPE("only requests to HTTPS are allowed", HTTP_REQUEST_FORBIDDEN, url); if (url.protocol !== "https:" && url.protocol !== "http:") throw OPE("only HTTP and HTTPS requests are allowed", REQUEST_PROTOCOL_FORBIDDEN, url); } function validateEndpoint(value, endpoint, useMtlsAlias, enforceHttps) { let url; if (typeof value !== "string" || !(url = URLParse(value))) throw OPE(`authorization server metadata does not contain a valid ${useMtlsAlias ? `"as.mtls_endpoint_aliases.${endpoint}"` : `"as.${endpoint}"`}`, value === void 0 ? MISSING_SERVER_METADATA : INVALID_SERVER_METADATA, { attribute: useMtlsAlias ? `mtls_endpoint_aliases.${endpoint}` : endpoint }); checkProtocol(url, enforceHttps); return url; } function resolveEndpoint(as, endpoint, useMtlsAlias, enforceHttps) { if (useMtlsAlias && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, useMtlsAlias, enforceHttps); return validateEndpoint(as[endpoint], endpoint, useMtlsAlias, enforceHttps); } function isDPoPNonceError(err) { if (err instanceof WWWAuthenticateChallengeError) { const { 0: challenge, length } = err.cause; return length === 1 && challenge.scheme === "dpop" && challenge.parameters.error === "use_dpop_nonce"; } if (err instanceof ResponseBodyError) return err.error === "use_dpop_nonce"; return false; } var ResponseBodyError = class extends Error { cause; code; error; status; error_description; response; constructor(message, options) { super(message, options); this.name = this.constructor.name; this.code = RESPONSE_BODY_ERROR; this.cause = options.cause; this.error = options.cause.error; this.status = options.response.status; this.error_description = options.cause.error_description; Object.defineProperty(this, "response", { enumerable: false, value: options.response }); Error.captureStackTrace?.(this, this.constructor); } }; var AuthorizationResponseError = class extends Error { cause; code; error; error_description; constructor(message, options) { super(message, options); this.name = this.constructor.name; this.code = AUTHORIZATION_RESPONSE_ERROR; this.cause = options.cause; this.error = options.cause.get("error"); this.error_description = options.cause.get("error_description") ?? void 0; Error.captureStackTrace?.(this, this.constructor); } }; var WWWAuthenticateChallengeError = class extends Error { cause; code; response; status; constructor(message, options) { super(message, options); this.name = this.constructor.name; this.code = WWW_AUTHENTICATE_CHALLENGE; this.cause = options.cause; this.status = options.response.status; this.response = options.response; Object.defineProperty(this, "response", { enumerable: false }); Error.captureStackTrace?.(this, this.constructor); } }; const schemeRE = /* @__PURE__ */ new RegExp("^[,\\s]*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)"); const quotedParamRE = /* @__PURE__ */ new RegExp("^[,\\s]*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)\\s*=\\s*\"((?:[^\"\\\\]|\\\\[\\s\\S])*)\"[,\\s]*(.*)"); const unquotedParamRE = /* @__PURE__ */ new RegExp("^[,\\s]*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)\\s*=\\s*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)[,\\s]*(.*)"); const token68ParamRE = /* @__PURE__ */ new RegExp("^([a-zA-Z0-9\\-\\._\\~\\+\\/]+={0,2})(?:$|[,\\s])(.*)"); function parseWwwAuthenticateChallenges(response) { if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1); const header = response.headers.get("www-authenticate"); if (header === null) return; const challenges = []; let rest = header; while (rest) { let match = rest.match(schemeRE); const scheme = match?.["1"].toLowerCase(); if (!scheme) return; const afterScheme = rest.substring(match[0].length); if (afterScheme && !afterScheme.match(/^[\s,]/)) return; const spaceMatch = afterScheme.match(/^\s+(.*)$/); const hasParameters = !!spaceMatch; rest = spaceMatch ? spaceMatch[1] : void 0; const parameters = {}; let token68; if (hasParameters) while (rest) { let key; let value; if (match = rest.match(quotedParamRE)) { [, key, value, rest] = match; if (value.includes("\\")) try { value = JSON.parse(`"${value}"`); } catch {} parameters[key.toLowerCase()] = value; continue; } if (match = rest.match(unquotedParamRE)) { [, key, value, rest] = match; parameters[key.toLowerCase()] = value; continue; } if (match = rest.match(token68ParamRE)) { if (Object.keys(parameters).length) break; [, token68, rest] = match; break; } return; } else rest = afterScheme || void 0; const challenge = { scheme, parameters }; if (token68) challenge.token68 = token68; challenges.push(challenge); } if (!challenges.length) return; return challenges; } async function parseOAuthResponseErrorBody(response) { if (response.status > 399 && response.status < 500) { assertReadableResponse(response); assertApplicationJson(response); try { const json = await response.clone().json(); if (isJsonObject(json) && typeof json.error === "string" && json.error.length) return json; } catch {} } } async function checkOAuthBodyError(response, expected, label) { if (response.status !== expected) { checkAuthenticationChallenges(response); let err; if (err = await parseOAuthResponseErrorBody(response)) { await response.body?.cancel(); throw new ResponseBodyError("server responded with an error in the response body", { cause: err, response }); } throw OPE(`"response" is not a conform ${label} response (unexpected HTTP status code)`, RESPONSE_IS_NOT_CONFORM, response); } } function assertDPoP(option) { if (!branded.has(option)) throw CodedTypeError$1("\"options.DPoP\" is not a valid DPoPHandle", ERR_INVALID_ARG_VALUE$1); } function getContentType(input) { return input.headers.get("content-type")?.split(";")[0]; } async function authenticatedRequest(as, client, clientAuthentication, url, body, headers, options) { await clientAuthentication(as, client, body, headers); headers.set("content-type", "application/x-www-form-urlencoded;charset=UTF-8"); return (options?.[customFetch$1] || fetch)(url.href, { body, headers: Object.fromEntries(headers.entries()), method: "POST", redirect: "manual", signal: signal$1(url, options?.signal) }); } async function tokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) { const url = resolveEndpoint(as, "token_endpoint", client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests$1] !== true); parameters.set("grant_type", grantType); const headers = prepareHeaders(options?.headers); headers.set("accept", "application/json"); if (options?.DPoP !== void 0) { assertDPoP(options.DPoP); await options.DPoP.addProof(url, headers, "POST"); } const response = await authenticatedRequest(as, client, clientAuthentication, url, parameters, headers, options); options?.DPoP?.cacheNonce(response, url); return response; } async function refreshTokenGrantRequest(as, client, clientAuthentication, refreshToken, options) { assertAs(as); assertClient(client); assertString$1(refreshToken, "\"refreshToken\""); const parameters = new URLSearchParams(options?.additionalParameters); parameters.set("refresh_token", refreshToken); return tokenEndpointRequest(as, client, clientAuthentication, "refresh_token", parameters, options); } const idTokenClaims = /* @__PURE__ */ new WeakMap(); const jwtRefs = /* @__PURE__ */ new WeakMap(); function getValidatedIdTokenClaims(ref) { if (!ref.id_token) return; const claims = idTokenClaims.get(ref); if (!claims) throw CodedTypeError$1("\"ref\" was already garbage collected or did not resolve from the proper sources", ERR_INVALID_ARG_VALUE$1); return claims; } async function processGenericAccessTokenResponse(as, client, response, additionalRequiredIdTokenClaims, decryptFn, recognizedTokenTypes) { assertAs(as); assertClient(client); if (!looseInstanceOf(response, Response)) throw CodedTypeError$1("\"response\" must be an instance of Response", ERR_INVALID_ARG_TYPE$1); await checkOAuthBodyError(response, 200, "Token Endpoint"); assertReadableResponse(response); const json = await getResponseJsonBody(response); assertString$1(json.access_token, "\"response\" body \"access_token\" property", INVALID_RESPONSE, { body: json }); assertString$1(json.token_type, "\"response\" body \"token_type\" property", INVALID_RESPONSE, { body: json }); json.token_type = json.token_type.toLowerCase(); if (json.expires_in !== void 0) { let expiresIn = typeof json.expires_in !== "number" ? parseFloat(json.expires_in) : json.expires_in; assertNumber(expiresIn, true, "\"response\" body \"expires_in\" property", INVALID_RESPONSE, { body: json }); json.expires_in = expiresIn; } if (json.refresh_token !== void 0) assertString$1(json.refresh_token, "\"response\" body \"refresh_token\" property", INVALID_RESPONSE, { body: json }); if (json.scope !== void 0 && typeof json.scope !== "string") throw OPE("\"response\" body \"scope\" property must be a string", INVALID_RESPONSE, { body: json }); if (json.id_token !== void 0) { assertString$1(json.id_token, "\"response\" body \"id_token\" property", INVALID_RESPONSE, { body: json }); const requiredClaims = [ "aud", "exp", "iat", "iss", "sub" ]; if (client.require_auth_time === true) requiredClaims.push("auth_time"); if (client.default_max_age !== void 0) { assertNumber(client.default_max_age, true, "\"client.default_max_age\""); requiredClaims.push("auth_time"); } if (additionalRequiredIdTokenClaims?.length) requiredClaims.push(...additionalRequiredIdTokenClaims); const { claims, jwt } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(void 0, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, "RS256"), getClockSkew(client), getClockTolerance(client), decryptFn).then(validatePresence.bind(void 0, requiredClaims)).then(validateIssuer.bind(void 0, as)).then(validateAudience.bind(void 0, client.client_id)); if (Array.isArray(claims.aud) && claims.aud.length !== 1) { if (claims.azp === void 0) throw OPE("ID Token \"aud\" (audience) claim includes additional untrusted audiences", JWT_CLAIM_COMPARISON, { claims, claim: "aud" }); if (claims.azp !== client.client_id) throw OPE("unexpected ID Token \"azp\" (authorized party) claim value", JWT_CLAIM_COMPARISON, { expected: client.client_id, claims, claim: "azp" }); } if (claims.auth_time !== void 0) assertNumber(claims.auth_time, true, "ID Token \"auth_time\" (authentication time)", INVALID_RESPONSE, { claims }); jwtRefs.set(response, jwt); idTokenClaims.set(json, claims); } if (recognizedTokenTypes?.[json.token_type] !== void 0) recognizedTokenTypes[json.token_type](response, json); else if (json.token_type !== "dpop" && json.token_type !== "bearer") throw new UnsupportedOperationError("unsupported `token_type` value", { cause: { body: json } }); return json; } function checkAuthenticationChallenges(response) { let challenges; if (challenges = parseWwwAuthenticateChallenges(response)) throw new WWWAuthenticateChallengeError("server responded with a challenge in the WWW-Authenticate HTTP Header", { cause: challenges, response }); } async function processRefreshTokenResponse(as, client, response, options) { return processGenericAccessTokenResponse(as, client, response, void 0, options?.[jweDecrypt], options?.recognizedTokenTypes); } function validateAudience(expected, result) { if (Array.isArray(result.claims.aud)) { if (!result.claims.aud.includes(expected)) throw OPE("unexpected JWT \"aud\" (audience) claim value", JWT_CLAIM_COMPARISON, { expected, claims: result.claims, claim: "aud" }); } else if (result.claims.aud !== expected) throw OPE("unexpected JWT \"aud\" (audience) claim value", JWT_CLAIM_COMPARISON, { expected, claims: result.claims, claim: "aud" }); return result; } function validateIssuer(as, result) { const expected = as[_expectedIssuer]?.(result) ?? as.issuer; if (result.claims.iss !== expected) throw OPE("unexpected JWT \"iss\" (issuer) claim value", JWT_CLAIM_COMPARISON, { expected, claims: result.claims, claim: "iss" }); return result; } const branded = /* @__PURE__ */ new WeakSet(); function brand(searchParams) { branded.add(searchParams); return searchParams; } const nopkce = Symbol(); async function authorizationCodeGrantRequest(as, client, clientAuthentication, callbackParameters, redirectUri, codeVerifier, options) { assertAs(as); assertClient(client); if (!branded.has(callbackParameters)) throw CodedTypeError$1("\"callbackParameters\" must be an instance of URLSearchParams obtained from \"validateAuthResponse()\", or \"validateJwtAuthResponse()", ERR_INVALID_ARG_VALUE$1); assertString$1(redirectUri, "\"redirectUri\""); const code = getURLSearchParameter(callbackParameters, "code"); if (!code) throw OPE("no authorization code in \"callbackParameters\"", INVALID_RESPONSE); const parameters = new URLSearchParams(options?.additionalParameters); parameters.set("redirect_uri", redirectUri); parameters.set("code", code); if (codeVerifier !== nopkce) { assertString$1(codeVerifier, "\"codeVerifier\""); parameters.set("code_verifier", codeVerifier); } return tokenEndpointRequest(as, client, clientAuthentication, "authorization_code", parameters, options); } const jwtClaimNames = { aud: "audience", c_hash: "code hash", client_id: "client id", exp: "expiration time", iat: "issued at", iss: "issuer", jti: "jwt id", nonce: "nonce", s_hash: "state hash", sub: "subject", ath: "access token hash", htm: "http method", htu: "http uri", cnf: "confirmation", auth_time: "authentication time" }; function validatePresence(required, result) { for (const claim of required) if (result.claims[claim] === void 0) throw OPE(`JWT "${claim}" (${jwtClaimNames[claim]}) claim missing`, INVALID_RESPONSE, { claims: result.claims }); return result; } const expectNoNonce = Symbol(); const skipAuthTimeCheck = Symbol(); async function processAuthorizationCodeResponse(as, client, response, options) { if (typeof options?.expectedNonce === "string" || typeof options?.maxAge === "number" || options?.requireIdToken) return processAuthorizationCodeOpenIDResponse(as, client, response, options.expectedNonce, options.maxAge, options[jweDecrypt], options.recognizedTokenTypes); return processAuthorizationCodeOAuth2Response(as, client, response, options?.[jweDecrypt], options?.recognizedTokenTypes); } async function processAuthorizationCodeOpenIDResponse(as, client, response, expectedNonce, maxAge, decryptFn, recognizedTokenTypes) { const additionalRequiredClaims = []; switch (expectedNonce) { case void 0: expectedNonce = expectNoNonce; break; case expectNoNonce: break; default: assertString$1(expectedNonce, "\"expectedNonce\" argument"); additionalRequiredClaims.push("nonce"); } maxAge ??= client.default_max_age; switch (maxAge) { case void 0: maxAge = skipAuthTimeCheck; break; case skipAuthTimeCheck: break; default: assertNumber(maxAge, true, "\"maxAge\" argument"); additionalRequiredClaims.push("auth_time"); } const result = await processGenericAccessTokenResponse(as, client, response, additionalRequiredClaims, decryptFn, recognizedTokenTypes); assertString$1(result.id_token, "\"response\" body \"id_token\" property", INVALID_RESPONSE, { body: result }); const claims = getValidatedIdTokenClaims(result); if (maxAge !== skipAuthTimeCheck) { const now = epochTime() + getClockSkew(client); const tolerance = getClockTolerance(client); if (claims.auth_time + maxAge < now - tolerance) throw OPE("too much time has elapsed since the last End-User authentication", JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: "auth_time" }); } if (expectedNonce === expectNoNonce) { if (claims.nonce !== void 0) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, { expected: void 0, claims, claim: "nonce" }); } else if (claims.nonce !== expectedNonce) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, { expected: expectedNonce, claims, claim: "nonce" }); return result; } async function processAuthorizationCodeOAuth2Response(as, client, response, decryptFn, recognizedTokenTypes) { const result = await processGenericAccessTokenResponse(as, client, response, void 0, decryptFn, recognizedTokenTypes); const claims = getValidatedIdTokenClaims(result); if (claims) { if (client.default_max_age !== void 0) { assertNumber(client.default_max_age, true, "\"client.default_max_age\""); const now = epochTime() + getClockSkew(client); const tolerance = getClockTolerance(client); if (claims.auth_time + client.default_max_age < now - tolerance) throw OPE("too much time has elapsed since the last End-User authentication", JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: "auth_time" }); } if (claims.nonce !== void 0) throw OPE("unexpected ID Token \"nonce\" claim value", JWT_CLAIM_COMPARISON, { expected: void 0, claims, claim: "nonce" }); } return result; } const WWW_AUTHENTICATE_CHALLENGE = "OAUTH_WWW_AUTHENTICATE_CHALLENGE"; const RESPONSE_BODY_ERROR = "OAUTH_RESPONSE_BODY_ERROR"; const UNSUPPORTED_OPERATION = "OAUTH_UNSUPPORTED_OPERATION"; const AUTHORIZATION_RESPONSE_ERROR = "OAUTH_AUTHORIZATION_RESPONSE_ERROR"; const PARSE_ERROR = "OAUTH_PARSE_ERROR"; const INVALID_RESPONSE = "OAUTH_INVALID_RESPONSE"; const RESPONSE_IS_NOT_JSON = "OAUTH_RESPONSE_IS_NOT_JSON"; const RESPONSE_IS_NOT_CONFORM = "OAUTH_RESPONSE_IS_NOT_CONFORM"; const HTTP_REQUEST_FORBIDDEN = "OAUTH_HTTP_REQUEST_FORBIDDEN"; const REQUEST_PROTOCOL_FORBIDDEN = "OAUTH_REQUEST_PROTOCOL_FORBIDDEN"; const JWT_TIMESTAMP_CHECK = "OAUTH_JWT_TIMESTAMP_CHECK_FAILED"; const JWT_CLAIM_COMPARISON = "OAUTH_JWT_CLAIM_COMPARISON_FAILED"; const JSON_ATTRIBUTE_COMPARISON = "OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED"; const MISSING_SERVER_METADATA = "OAUTH_MISSING_SERVER_METADATA"; const INVALID_SERVER_METADATA = "OAUTH_INVALID_SERVER_METADATA"; function assertReadableResponse(response) { if (response.bodyUsed) throw CodedTypeError$1("\"response\" body has been used already", ERR_INVALID_ARG_VALUE$1); } async function validateJwt(jws, checkAlg, clockSkew, clockTolerance, decryptJwt) { let { 0: protectedHeader, 1: payload, length } = jws.split("."); if (length === 5) if (decryptJwt !== void 0) { jws = await decryptJwt(jws); ({0: protectedHeader, 1: payload, length} = jws.split(".")); } else throw new UnsupportedOperationError("JWE decryption is not configured", { cause: jws }); if (length !== 3) throw OPE("Invalid JWT", INVALID_RESPONSE, jws); let header; try { header = JSON.parse(buf(b64u(protectedHeader))); } catch (cause) { throw OPE("failed to parse JWT Header body as base64url encoded JSON", PARSE_ERROR, cause); } if (!isJsonObject(header)) throw OPE("JWT Header must be a top level object", INVALID_RESPONSE, jws); checkAlg(header); if (header.crit !== void 0) throw new UnsupportedOperationError("no JWT \"crit\" header parameter extensions are supported", { cause: { header } }); let claims; try { claims = JSON.parse(buf(b64u(payload))); } catch (cause) { throw OPE("failed to parse JWT Payload body as base64url encoded JSON", PARSE_ERROR, cause); } if (!isJsonObject(claims)) throw OPE("JWT Payload must be a top level object", INVALID_RESPONSE, jws); const now = epochTime() + clockSkew; if (claims.exp !== void 0) { if (typeof claims.exp !== "number") throw OPE("unexpected JWT \"exp\" (expiration time) claim type", INVALID_RESPONSE, { claims }); if (claims.exp <= now - clockTolerance) throw OPE("unexpected JWT \"exp\" (expiration time) claim value, expiration is past current timestamp", JWT_TIMESTAMP_CHECK, { claims, now, tolerance: clockTolerance, claim: "exp" }); } if (claims.iat !== void 0) { if (typeof claims.iat !== "number") throw OPE("unexpected JWT \"iat\" (issued at) claim type", INVALID_RESPONSE, { claims }); } if (claims.iss !== void 0) { if (typeof claims.iss !== "string") throw OPE("unexpected JWT \"iss\" (issuer) claim type", INVALID_RESPONSE, { claims }); } if (claims.nbf !== void 0) { if (typeof claims.nbf !== "number") throw OPE("unexpected JWT \"nbf\" (not before) claim type", INVALID_RESPONSE, { claims }); if (claims.nbf > now + clockTolerance) throw OPE("unexpected JWT \"nbf\" (not before) claim value", JWT_TIMESTAMP_CHECK, { claims, now, tolerance: clockTolerance, claim: "nbf" }); } if (claims.aud !== void 0) { if (typeof claims.aud !== "string" && !Array.isArray(claims.aud)) throw OPE("unexpected JWT \"aud\" (audience) claim type", INVALID_RESPONSE, { claims }); } return { header, claims, jwt: jws }; } async function consumeStream(request) { if (request.bodyUsed) throw CodedTypeError$1("form_post Request instances must contain a readable body", ERR_INVALID_ARG_VALUE$1, { cause: request }); return request.text(); } async function formPostResponse(request) { if (request.method !== "POST") throw CodedTypeError$1("form_post responses are expected to use the POST method", ERR_INVALID_ARG_VALUE$1, { cause: request }); if (getContentType(request) !== "application/x-www-form-urlencoded") throw CodedTypeError$1("form_post responses are expected to use the application/x-www-form-urlencoded content-type", ERR_INVALID_ARG_VALUE$1, { cause: request }); return consumeStream(request); } function checkSigningAlgorithm(client, issuer, fallback, header) { if (client !== void 0) { if (typeof client === "string" ? header.alg !== client : !client.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, { header, expected: client, reason: "client configuration" }); return; } if (Array.isArray(issuer)) { if (!issuer.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, { header, expected: issuer, reason: "authorization server metadata" }); return; } if (fallback !== void 0) { if (typeof fallback === "string" ? header.alg !== fallback : typeof fallback === "function" ? !fallback(header.alg) : !fallback.includes(header.alg)) throw OPE("unexpected JWT \"alg\" header parameter", INVALID_RESPONSE, { header, expected: fallback, reason: "default value" }); return; } throw OPE("missing client or server configuration to verify used JWT \"alg\" header parameter", void 0, { client, issuer, fallback }); } function getURLSearchParameter(parameters, name) { const { 0: value, length } = parameters.getAll(name); if (length > 1) throw OPE(`"${name}" parameter must be provided only once`, INVALID_RESPONSE); return value; } const skipStateCheck = Symbol(); const expectNoState = Symbol(); function validateAuthResponse(as, client, parameters, expectedState) { assertAs(as); assertClient(client); if (parameters instanceof URL) parameters = parameters.searchParams; if (!(parameters instanceof URLSearchParams)) throw CodedTypeError$1("\"parameters\" must be an instance of URLSearchParams, or URL", ERR_INVALID_ARG_TYPE$1); if (getURLSearchParameter(parameters, "response")) throw OPE("\"parameters\" contains a JARM response, use validateJwtAuthResponse() instead of validateAuthResponse()", INVALID_RESPONSE, { parameters }); const iss = getURLSearchParameter(parameters, "iss"); const state = getURLSearchParameter(parameters, "state"); if (!iss && as.authorization_response_iss_parameter_supported) throw OPE("response parameter \"iss\" (issuer) missing", INVALID_RESPONSE, { parameters }); if (iss && iss !== as.issuer) throw OPE("unexpected \"iss\" (issuer) response parameter value", INVALID_RESPONSE, { expected: as.issuer, parameters }); switch (expectedState) { case void 0: case expectNoState: if (state !== void 0) throw OPE("unexpected \"state\" response parameter encountered", INVALID_RESPONSE, { expected: void 0, parameters }); break; case skipStateCheck: break; default: assertString$1(expectedState, "\"expectedState\" argument"); if (state !== expectedState) throw OPE(state === void 0 ? "response parameter \"state\" missing" : "unexpected \"state\" response parameter value", INVALID_RESPONSE, { expected: expectedState, parameters }); } if (getURLSearchParameter(parameters, "error")) throw new AuthorizationResponseError("authorization response from the server is an error", { cause: parameters }); const id_token = getURLSearchParameter(parameters, "id_token"); const token = getURLSearchParameter(parameters, "token"); if (id_token !== void 0 || token !== void 0) throw new UnsupportedOperationError("implicit and hybrid flows are not supported"); return brand(new URLSearchParams(parameters)); } async function getResponseJsonBody(response, check = assertApplicationJson) { let json; try { json = await response.json(); } catch (cause) { check(response); throw OPE("failed to parse \"response\" body as JSON", PARSE_ERROR, cause); } if (!isJsonObject(json)) throw OPE("\"response\" body must be a top level object", INVALID_RESPONSE, { body: json }); return json; } const _nodiscoverycheck = Symbol(); const _expectedIssuer = Symbol(); //#endregion //#region ../../../../node_modules/openid-client/build/index.js let headers; let USER_AGENT; if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) { USER_AGENT = `openid-client/v6.8.4`; headers = { "user-agent": USER_AGENT }; } const int = (config) => { return props.get(config); }; let props; let tbi; function ClientSecretPost(clientSecret) { if (clientSecret !== void 0) return ClientSecretPost$1(clientSecret); tbi ||= /* @__PURE__ */ new WeakMap(); return (as, client, body, headers) => { let auth; if (!(auth = tbi.get(client))) { assertString(client.client_secret, "\"metadata.client_secret\""); auth = ClientSecretPost$1(client.client_secret); tbi.set(client, auth); } return auth(as, client, body, headers); }; } function assertString(input, it) { if (typeof input !== "string") throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE); if (input.length === 0) throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE); } function None() { return None$1(); } const customFetch = customFetch$1; const ERR_INVALID_ARG_VALUE = "ERR_INVALID_ARG_VALUE"; const ERR_INVALID_ARG_TYPE = "ERR_INVALID_ARG_TYPE"; function CodedTypeError(message, code, cause) { const err = new TypeError(message, { cause }); Object.assign(err, { code }); return err; } function calculatePKCECodeChallenge(codeVerifier) { return calculatePKCECodeChallenge$1(codeVerifier); } function randomPKCECodeVerifier() { return generateRandomCodeVerifier(); } function randomState() { return generateRandomState(); } var ClientError = class extends Error { code; constructor(message, options) { super(message, options); this.name = this.constructor.name; this.code = options?.code; Error.captureStackTrace?.(this, this.constructor); } }; new TextDecoder(); function e(msg, cause, code) { return new ClientError(msg, { cause, code }); } function errorHandler(err) { if (err instanceof TypeError || err instanceof ClientError || err instanceof ResponseBodyError || err instanceof AuthorizationResponseError || err instanceof WWWAuthenticateChallengeError) throw err; if (err instanceof OperationProcessingError) switch (err.code) { case HTTP_REQUEST_FORBIDDEN: throw e("only requests to HTTPS are allowed", err, err.code); case REQUEST_PROTOCOL_FORBIDDEN: throw e("only requests to HTTP or HTTPS are allowed", err, err.code); case RESPONSE_IS_NOT_CONFORM: throw e("unexpected HTTP response status code", err.cause, err.code); case RESPONSE_IS_NOT_JSON: throw e("unexpected response content-type", err.cause, err.code); case PARSE_ERROR: throw e("parsing error occured", err, err.code); case INVALID_RESPONSE: throw e("invalid response encountered", err, err.code); case JWT_CLAIM_COMPARISON: throw e("unexpected JWT claim value encountered", err, err.code); case JSON_ATTRIBUTE_COMPARISON: throw e("unexpected JSON attribute value encountered", err, err.code); case JWT_TIMESTAMP_CHECK: throw e("JWT timestamp claim value failed validation", err, err.code); default: throw e(err.message, err, err.code); } if (err instanceof UnsupportedOperationError) throw e("unsupported operation", err, err.code); if (err instanceof DOMException) switch (err.name) { case "OperationError": throw e("runtime operation error", err, UNSUPPORTED_OPERATION); case "NotSupportedError": throw e("runtime unsupported operation", err, UNSUPPORTED_OPERATION); case "TimeoutError": throw e("operation timed out", err, "OAUTH_TIMEOUT"); case "AbortError": throw e("operation aborted", err, "OAUTH_ABORT"); } throw new ClientError("something went wrong", { cause: err }); } function handleEntraId(server, as, options) { if (server.origin === "https://login.microsoftonline.com" && (!options?.algorithm || options.algorithm === "oidc")) { as[kEntraId] = true; return true; } return false; } function handleB2Clogin(server, options) { if (server.hostname.endsWith(".b2clogin.com") && (!options?.algorithm || options.algorithm === "oidc")) return true; return false; } async function discovery(server, clientId, metadata, clientAuthentication, options) { const instance = new Configuration(await performDiscovery(server, options), clientId, metadata, clientAuthentication); let internals = int(instance); if (options?.[customFetch]) internals.fetch = options[customFetch]; if (options?.timeout) internals.timeout = options.timeout; if (options?.execute) for (const extension of options.execute) extension(instance); return instance; } async function performDiscovery(server, options) { if (!(server instanceof URL)) throw CodedTypeError("\"server\" must be an instance of URL", ERR_INVALID_ARG_TYPE); const resolve = !server.href.includes("/.well-known/"); const timeout = options?.timeout ?? 30; const signal = AbortSignal.timeout(timeout * 1e3); const as = await (resolve ? discoveryRequest(server, { algorithm: options?.algorithm, [customFetch$1]: options?.[customFetch], [allowInsecureRequests$1]: options?.execute?.includes(allowInsecureRequests), signal, headers: new Headers(headers) }) : (options?.[customFetch] || fetch)((() => { checkProtocol(server, options?.execute?.includes(allowInsecureRequests) ? false : true); return server.href; })(), { headers: Object.fromEntries(new Headers({ accept: "application/json", ...headers }).entries()), body: void 0, method: "GET", redirect: "manual", signal })).then((response) => processDiscoveryResponse(_nodiscoverycheck, response)).catch(errorHandler); if (resolve && new URL(as.issuer).href !== server.href) handleEntraId(server, as, options) || handleB2Clogin(server, options) || (() => { throw new ClientError("discovered metadata issuer does not match the expected issuer", { code: "OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED", cause: { expected: server.href, body: as, attribute: "issuer" } }); })(); return as; } function getServerHelpers(metadata) { return { supportsPKCE: { __proto__: null, value(method = "S256") { return metadata.code_challenge_methods_supported?.includes(method) === true; } } }; } function addServerHelpers(metadata) { Object.defineProperties(metadata, getServerHelpers(metadata)); } const kEntraId = Symbol(); var Configuration = class { constructor(server, clientId, metadata, clientAuthentication) { if (typeof clientId !== "string" || !clientId.length) throw CodedTypeError("\"clientId\" must be a non-empty string", ERR_INVALID_ARG_TYPE); if (typeof metadata === "string") metadata = { client_secret: metadata }; if (metadata?.client_id !== void 0 && clientId !== metadata.client_id) throw CodedTypeError("\"clientId\" and \"metadata.client_id\" must be the same", ERR_INVALID_ARG_VALUE); const client = { ...structuredClone(metadata), client_id: clientId }; client[clockSkew] = metadata?.[clockSkew] ?? 0; client[clockTolerance] = metadata?.[clockTolerance] ?? 30; let auth; if (clientAuthentication) auth = clientAuthentication; else if (typeof client.client_secret === "string" && client.client_secret.length) auth = ClientSecretPost(client.client_secret); else auth = None(); let c = Object.freeze(client); const clone = structuredClone(server); if (kEntraId in server) clone[_expectedIssuer] = ({ claims: { tid } }) => server.issuer.replace("{tenantid}", tid); let as = Object.freeze(clone); props ||= /* @__PURE__ */ new WeakMap(); props.set(this, { __proto__: null, as, c, auth, tlsOnly: true, jwksCache: {} }); } serverMetadata() { const metadata = structuredClone(int(this).as); addServerHelpers(metadata); return metadata; } clientMetadata() { return structuredClone(int(this).c); } get timeout() { return int(this).timeout; } set timeout(value) { int(this).timeout = value; } get [customFetch]() { return int(this).fetch; } set [customFetch](value) { int(this).fetch = value; } }; Object.freeze(Configuration.prototype); function getHelpers(response) { let exp = void 0; if (response.expires_in !== void 0) { const now = /* @__PURE__ */ new Date(); now.setSeconds(now.getSeconds() + response.expires_in); exp = now.getTime(); } return { expiresIn: { __proto__: null, value() { if (exp) { const now = Date.now(); if (exp > now) return Math.floor((exp - now) / 1e3); return 0; } } }, claims: { __proto__: null, value() { try { return getValidatedIdTokenClaims(this); } catch { return; } } } }; } function addHelpers(response) { Object.defineProperties(response, getHelpers(response)); } function allowInsecureRequests(config) { int(config).tlsOnly = false; } function stripParams(url) { url = new URL(url); url.search = ""; url.hash = ""; return url.href; } function webInstanceOf(input, toStringTag) { try { return Object.getPrototypeOf(input)[Symbol.toStringTag] === toStringTag; } catch { return false; } } async function authorizationCodeGrant(config, currentUrl, checks, tokenEndpointParameters, options) { checkConfig(config); if (options?.flag !== retry && !(currentUrl instanceof URL) && !webInstanceOf(currentUrl, "Request")) throw CodedTypeError("\"currentUrl\" must be an instance of URL, or Request", ERR_INVALID_ARG_TYPE); let authResponse; let redirectUri; const { as, c, auth, fetch, tlsOnly, jarm, hybrid, nonRepudiation, timeout, decrypt, implicit } = int(config); if (options?.flag === retry) { authResponse = options.authResponse; redirectUri = options.redirectUri; } else { if (!(currentUrl instanceof URL)) { const request = currentUrl; currentUrl = new URL(currentUrl.url); switch (request.method) { case "GET": break; case "POST": const params = new URLSearchParams(await formPostResponse(request)); if (hybrid) currentUrl.hash = params.toString(); else for (const [k, v] of params.entries()) currentUrl.searchParams.append(k, v); break; default: throw CodedTypeError("unexpected Request HTTP method", ERR_INVALID_ARG_VALUE); } } redirectUri = stripParams(currentUrl); switch (true) { case !!jarm: authResponse = await jarm(currentUrl, checks?.expectedState); break; case !!hybrid: authResponse = await hybrid(currentUrl, checks?.expectedNonce, checks?.expectedState, checks?.maxAge); break; case !!implicit: throw new TypeError("authorizationCodeGrant() cannot be used by response_type=id_token clients"); default: try { authResponse = validateAuthResponse(as, c, currentUrl.searchParams, checks?.expectedState); } catch (err) { errorHandler(err); } } } const response = await authorizationCodeGrantRequest(as, c, auth, authResponse, redirectUri, checks?.pkceCodeVerifier || nopkce, { additionalParameters: tokenEndpointParameters, [customFetch$1]: fetch, [allowInsecureRequests$1]: !tlsOnly, DPoP: options?.DPoP, headers: new Headers(headers), signal: signal(timeout) }).catch(errorHandler); if (typeof checks?.expectedNonce === "string" || typeof checks?.maxAge === "number") checks.idTokenExpected = true; const p = processAuthorizationCodeResponse(as, c, response, { expectedNonce: checks?.expectedNonce, maxAge: checks?.maxAge, requireIdToken: checks?.idTokenExpected, [jweDecrypt]: decrypt }); let result; try { result = await p; } catch (err) { if (retryable(err, options)) return authorizationCodeGrant(config, void 0, checks, tokenEndpointParameters, { ...options, flag: retry, authResponse, redirectUri }); errorHandler(err); } result.id_token && await nonRepudiation?.(response); addHelpers(result); return result; } async function refreshTokenGrant(config, refreshToken, parameters, options) { checkConfig(config); parameters = new URLSearchParams(parameters); const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config); const response = await refreshTokenGrantRequest(as, c, auth, refreshToken, { [customFetch$1]: fetch, [allowInsecureRequests$1]: !tlsOnly, additionalParameters: parameters, DPoP: options?.DPoP, headers: new Headers(headers), signal: signal(timeout) }).catch(errorHandler); const p = processRefreshTokenResponse(as, c, response, { [jweDecrypt]: decrypt }); let result; try { result = await p; } catch (err) { if (retryable(err, options)) return refreshTokenGrant(config, refreshToken, parameters, { ...options, flag: retry }); errorHandler(err); } result.id_token && await nonRepudiation?.(response); addHelpers(result); return result; } function buildAuthorizationUrl(config, parameters) { checkConfig(config); const { as, c, tlsOnly, hybrid, jarm, implicit } = int(config); const authorizationEndpoint = resolveEndpoint(as, "authorization_endpoint", false, tlsOnly); parameters = new URLSearchParams(parameters); if (!parameters.has("client_id")) parameters.set("client_id", c.client_id); if (!parameters.has("request_uri") && !parameters.has("request")) { if (!parameters.has("response_type")) parameters.set("response_type", hybrid ? "code id_token" : implicit ? "id_token" : "code"); if (implicit && !parameters.has("nonce")) throw CodedTypeError("response_type=id_token clients must provide a nonce parameter in their authorization request parameters", ERR_INVALID_ARG_VALUE); if (jarm) parameters.set("response_mode", "jwt"); } for (const [k, v] of parameters.entries()) authorizationEndpoint.searchParams.append(k, v); return authorizationEndpoint; } function buildEndSessionUrl(config, parameters) { checkConfig(config); const { as, c, tlsOnly } = int(config); const endSessionEndpoint = resolveEndpoint(as, "end_session_endpoint", false, tlsOnly); parameters = new URLSearchParams(parameters); if (!parameters.has("client_id")) parameters.set("client_id", c.client_i