1import { 2 require_react 3} from "/node_modules/.vite/deps/chunk-4AFIVRCK.js?v=ccc16c5c"; 4import { 5 __toESM 6} from "/node_modules/.vite/deps/chunk-DP4XHQAG.js?v=ccc16c5c"; 7
vendor: 112 bytes, lines 8-10
8// node_modules/react-oidc-context/dist/esm/react-oidc-context.js 9var import_react = __toESM(require_react()); 10
vendor: 1,575 bytes, lines 11-66
11// node_modules/jwt-decode/build/esm/index.js 12var InvalidTokenError = class extends Error { 13}; 14InvalidTokenError.prototype.name = "InvalidTokenError"; 15function b64DecodeUnicode(str) { 16 return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => { 17 let code = p.charCodeAt(0).toString(16).toUpperCase(); 18 if (code.length < 2) { 19 code = "0" + code; 20 } 21 return "%" + code; 22 })); 23} 24function base64UrlDecode(str) { 25 let output = str.replace(/-/g, "+").replace(/_/g, "/"); 26 switch (output.length % 4) { 27 case 0: 28 break; 29 case 2: 30 output += "=="; 31 break; 32 case 3: 33 output += "="; 34 break; 35 default: 36 throw new Error("base64 string is not of the correct length"); 37 } 38 try { 39 return b64DecodeUnicode(output); 40 } catch (err) { 41 return atob(output); 42 } 43} 44function jwtDecode(token, options) { 45 if (typeof token !== "string") { 46 throw new InvalidTokenError("Invalid token specified: must be a string"); 47 } 48 options || (options = {}); 49 const pos = options.header === true ? 0 : 1; 50 const part = token.split(".")[pos]; 51 if (typeof part !== "string") { 52 throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`); 53 } 54 let decoded; 55 try { 56 decoded = base64UrlDecode(part); 57 } catch (e) { 58 throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`); 59 } 60 try { 61 return JSON.parse(decoded); 62 } catch (e) { 63 throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`); 64 } 65} 66
vendor: 119,643 bytes, lines 67-3564
67// node_modules/oidc-client-ts/dist/esm/oidc-client-ts.js 68var nopLogger = { 69 debug: () => void 0, 70 info: () => void 0, 71 warn: () => void 0, 72 error: () => void 0 73}; 74var level; 75var logger; 76var Log = ((Log2) => { 77 Log2[Log2["NONE"] = 0] = "NONE"; 78 Log2[Log2["ERROR"] = 1] = "ERROR"; 79 Log2[Log2["WARN"] = 2] = "WARN"; 80 Log2[Log2["INFO"] = 3] = "INFO"; 81 Log2[Log2["DEBUG"] = 4] = "DEBUG"; 82 return Log2; 83})(Log || {}); 84((Log2) => { 85 function reset() { 86 level = 3; 87 logger = nopLogger; 88 } 89 Log2.reset = reset; 90 function setLevel(value) { 91 if (!(0 <= value && value <= 4)) { 92 throw new Error("Invalid log level"); 93 } 94 level = value; 95 } 96 Log2.setLevel = setLevel; 97 function setLogger(value) { 98 logger = value; 99 } 100 Log2.setLogger = setLogger; 101})(Log || (Log = {})); 102var Logger = class _Logger { 103 constructor(_name) { 104 this._name = _name; 105 } 106 /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ 107 debug(...args) { 108 if (level >= 4) { 109 logger.debug(_Logger._format(this._name, this._method), ...args); 110 } 111 } 112 info(...args) { 113 if (level >= 3) { 114 logger.info(_Logger._format(this._name, this._method), ...args); 115 } 116 } 117 warn(...args) { 118 if (level >= 2) { 119 logger.warn(_Logger._format(this._name, this._method), ...args); 120 } 121 } 122 error(...args) { 123 if (level >= 1) { 124 logger.error(_Logger._format(this._name, this._method), ...args); 125 } 126 } 127 /* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */ 128 throw(err) { 129 this.error(err); 130 throw err; 131 } 132 create(method) { 133 const methodLogger = Object.create(this); 134 methodLogger._method = method; 135 methodLogger.debug("begin"); 136 return methodLogger; 137 } 138 static createStatic(name, staticMethod) { 139 const staticLogger = new _Logger(`${name}.${staticMethod}`); 140 staticLogger.debug("begin"); 141 return staticLogger; 142 } 143 static _format(name, method) { 144 const prefix = `[${name}]`; 145 return method ? `${prefix} ${method}:` : prefix; 146 } 147 /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ 148 // helpers for static class methods 149 static debug(name, ...args) { 150 if (level >= 4) { 151 logger.debug(_Logger._format(name), ...args); 152 } 153 } 154 static info(name, ...args) { 155 if (level >= 3) { 156 logger.info(_Logger._format(name), ...args); 157 } 158 } 159 static warn(name, ...args) { 160 if (level >= 2) { 161 logger.warn(_Logger._format(name), ...args); 162 } 163 } 164 static error(name, ...args) { 165 if (level >= 1) { 166 logger.error(_Logger._format(name), ...args); 167 } 168 } 169 /* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */ 170}; 171Log.reset(); 172var JwtUtils = class { 173 // IMPORTANT: doesn't validate the token 174 static decode(token) { 175 try { 176 return jwtDecode(token); 177 } catch (err) { 178 Logger.error("JwtUtils.decode", err); 179 throw err; 180 } 181 } 182 static async generateSignedJwt(header, payload, privateKey) { 183 const encodedHeader = CryptoUtils.encodeBase64Url(new TextEncoder().encode(JSON.stringify(header))); 184 const encodedPayload = CryptoUtils.encodeBase64Url(new TextEncoder().encode(JSON.stringify(payload))); 185 const encodedToken = `${encodedHeader}.${encodedPayload}`; 186 const signature = await window.crypto.subtle.sign( 187 { 188 name: "ECDSA", 189 hash: { name: "SHA-256" } 190 }, 191 privateKey, 192 new TextEncoder().encode(encodedToken) 193 ); 194 const encodedSignature = CryptoUtils.encodeBase64Url(new Uint8Array(signature)); 195 return `${encodedToken}.${encodedSignature}`; 196 } 197 static async generateSignedJwtWithHmac(header, payload, secretKey) { 198 const encodedHeader = CryptoUtils.encodeBase64Url(new TextEncoder().encode(JSON.stringify(header))); 199 const encodedPayload = CryptoUtils.encodeBase64Url(new TextEncoder().encode(JSON.stringify(payload))); 200 const encodedToken = `${encodedHeader}.${encodedPayload}`; 201 const signature = await window.crypto.subtle.sign( 202 "HMAC", 203 secretKey, 204 new TextEncoder().encode(encodedToken) 205 ); 206 const encodedSignature = CryptoUtils.encodeBase64Url(new Uint8Array(signature)); 207 return `${encodedToken}.${encodedSignature}`; 208 } 209}; 210var UUID_V4_TEMPLATE = "10000000-1000-4000-8000-100000000000"; 211var toBase64 = (val) => btoa([...new Uint8Array(val)].map((chr) => String.fromCharCode(chr)).join("")); 212var _CryptoUtils = class _CryptoUtils2 { 213 static _randomWord() { 214 const arr = new Uint32Array(1); 215 crypto.getRandomValues(arr); 216 return arr[0]; 217 } 218 /** 219 * Generates RFC4122 version 4 guid 220 */ 221 static generateUUIDv4() { 222 const uuid = UUID_V4_TEMPLATE.replace( 223 /[018]/g, 224 (c) => (+c ^ _CryptoUtils2._randomWord() & 15 >> +c / 4).toString(16) 225 ); 226 return uuid.replace(/-/g, ""); 227 } 228 /** 229 * PKCE: Generate a code verifier 230 */ 231 static generateCodeVerifier() { 232 return _CryptoUtils2.generateUUIDv4() + _CryptoUtils2.generateUUIDv4() + _CryptoUtils2.generateUUIDv4(); 233 } 234 /** 235 * PKCE: Generate a code challenge 236 */ 237 static async generateCodeChallenge(code_verifier) { 238 if (!crypto.subtle) { 239 throw new Error("Crypto.subtle is available only in secure contexts (HTTPS)."); 240 } 241 try { 242 const encoder = new TextEncoder(); 243 const data = encoder.encode(code_verifier); 244 const hashed = await crypto.subtle.digest("SHA-256", data); 245 return toBase64(hashed).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); 246 } catch (err) { 247 Logger.error("CryptoUtils.generateCodeChallenge", err); 248 throw err; 249 } 250 } 251 /** 252 * Generates a base64-encoded string for a basic auth header 253 */ 254 static generateBasicAuth(client_id, client_secret) { 255 const encoder = new TextEncoder(); 256 const data = encoder.encode([client_id, client_secret].join(":")); 257 return toBase64(data); 258 } 259 /** 260 * Generates a hash of a string using a given algorithm 261 * @param alg 262 * @param message 263 */ 264 static async hash(alg, message) { 265 const msgUint8 = new TextEncoder().encode(message); 266 const hashBuffer = await crypto.subtle.digest(alg, msgUint8); 267 return new Uint8Array(hashBuffer); 268 } 269 /** 270 * Generates a rfc7638 compliant jwk thumbprint 271 * @param jwk 272 */ 273 static async customCalculateJwkThumbprint(jwk) { 274 let jsonObject; 275 switch (jwk.kty) { 276 case "RSA": 277 jsonObject = { 278 "e": jwk.e, 279 "kty": jwk.kty, 280 "n": jwk.n 281 }; 282 break; 283 case "EC": 284 jsonObject = { 285 "crv": jwk.crv, 286 "kty": jwk.kty, 287 "x": jwk.x, 288 "y": jwk.y 289 }; 290 break; 291 case "OKP": 292 jsonObject = { 293 "crv": jwk.crv, 294 "kty": jwk.kty, 295 "x": jwk.x 296 }; 297 break; 298 case "oct": 299 jsonObject = { 300 "crv": jwk.k, 301 "kty": jwk.kty 302 }; 303 break; 304 default: 305 throw new Error("Unknown jwk type"); 306 } 307 const utf8encodedAndHashed = await _CryptoUtils2.hash("SHA-256", JSON.stringify(jsonObject)); 308 return _CryptoUtils2.encodeBase64Url(utf8encodedAndHashed); 309 } 310 static async generateDPoPProof({ 311 url, 312 accessToken, 313 httpMethod, 314 keyPair, 315 nonce 316 }) { 317 let hashedToken; 318 let encodedHash; 319 const payload = { 320 "jti": window.crypto.randomUUID(), 321 "htm": httpMethod != null ? httpMethod : "GET", 322 "htu": url, 323 "iat": Math.floor(Date.now() / 1e3) 324 }; 325 if (accessToken) { 326 hashedToken = await _CryptoUtils2.hash("SHA-256", accessToken); 327 encodedHash = _CryptoUtils2.encodeBase64Url(hashedToken); 328 payload.ath = encodedHash; 329 } 330 if (nonce) { 331 payload.nonce = nonce; 332 } 333 try { 334 const publicJwk = await crypto.subtle.exportKey("jwk", keyPair.publicKey); 335 const header = { 336 "alg": "ES256", 337 "typ": "dpop+jwt", 338 "jwk": { 339 "crv": publicJwk.crv, 340 "kty": publicJwk.kty, 341 "x": publicJwk.x, 342 "y": publicJwk.y 343 } 344 }; 345 return await JwtUtils.generateSignedJwt(header, payload, keyPair.privateKey); 346 } catch (err) { 347 if (err instanceof TypeError) { 348 throw new Error(`Error exporting dpop public key: ${err.message}`); 349 } else { 350 throw err; 351 } 352 } 353 } 354 static async generateDPoPJkt(keyPair) { 355 try { 356 const publicJwk = await crypto.subtle.exportKey("jwk", keyPair.publicKey); 357 return await _CryptoUtils2.customCalculateJwkThumbprint(publicJwk); 358 } catch (err) { 359 if (err instanceof TypeError) { 360 throw new Error(`Could not retrieve dpop keys from storage: ${err.message}`); 361 } else { 362 throw err; 363 } 364 } 365 } 366 static async generateDPoPKeys() { 367 return await window.crypto.subtle.generateKey( 368 { 369 name: "ECDSA", 370 namedCurve: "P-256" 371 }, 372 false, 373 ["sign", "verify"] 374 ); 375 } 376 /** 377 * Generates a client assertion JWT for client_secret_jwt authentication 378 * @param client_id The client identifier 379 * @param client_secret The client secret 380 * @param audience The token endpoint URL (audience) 381 * @param algorithm The HMAC algorithm to use (HS256, HS384, HS512). Defaults to HS256 382 */ 383 static async generateClientAssertionJwt(client_id, client_secret, audience, algorithm = "HS256") { 384 const now = Math.floor(Date.now() / 1e3); 385 const header = { 386 "alg": algorithm, 387 "typ": "JWT" 388 }; 389 const payload = { 390 "iss": client_id, 391 "sub": client_id, 392 "aud": audience, 393 "jti": _CryptoUtils2.generateUUIDv4(), 394 "exp": now + 300, 395 // 5 minutes 396 "iat": now 397 }; 398 const hashMap = { 399 "HS256": "SHA-256", 400 "HS384": "SHA-384", 401 "HS512": "SHA-512" 402 }; 403 const hashFunction = hashMap[algorithm]; 404 if (!hashFunction) { 405 throw new Error(`Unsupported algorithm: ${algorithm}. Supported algorithms are: HS256, HS384, HS512`); 406 } 407 const encoder = new TextEncoder(); 408 const secretKey = await crypto.subtle.importKey( 409 "raw", 410 encoder.encode(client_secret), 411 { name: "HMAC", hash: hashFunction }, 412 false, 413 ["sign"] 414 ); 415 return await JwtUtils.generateSignedJwtWithHmac(header, payload, secretKey); 416 } 417}; 418_CryptoUtils.encodeBase64Url = (input) => { 419 return toBase64(input).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); 420}; 421var CryptoUtils = _CryptoUtils; 422var Event = class { 423 constructor(_name) { 424 this._name = _name; 425 this._callbacks = []; 426 this._logger = new Logger(`Event('${this._name}')`); 427 } 428 addHandler(cb) { 429 this._callbacks.push(cb); 430 return () => this.removeHandler(cb); 431 } 432 removeHandler(cb) { 433 const idx = this._callbacks.lastIndexOf(cb); 434 if (idx >= 0) { 435 this._callbacks.splice(idx, 1); 436 } 437 } 438 async raise(...ev) { 439 this._logger.debug("raise:", ...ev); 440 for (const cb of this._callbacks) { 441 await cb(...ev); 442 } 443 } 444}; 445var PopupUtils = class { 446 /** 447 * Populates a map of window features with a placement centered in front of 448 * the current window. If no explicit width is given, a default value is 449 * binned into [800, 720, 600, 480, 360] based on the current window's width. 450 */ 451 static center({ ...features }) { 452 var _a, _b, _c; 453 if (features.width == null) 454 features.width = (_a = [800, 720, 600, 480].find((width) => width <= window.outerWidth / 1.618)) != null ? _a : 360; 455 (_b = features.left) != null ? _b : features.left = Math.max(0, Math.round(window.screenX + (window.outerWidth - features.width) / 2)); 456 if (features.height != null) 457 (_c = features.top) != null ? _c : features.top = Math.max(0, Math.round(window.screenY + (window.outerHeight - features.height) / 2)); 458 return features; 459 } 460 static serialize(features) { 461 return Object.entries(features).filter(([, value]) => value != null).map(([key, value]) => `${key}=${typeof value !== "boolean" ? value : value ? "yes" : "no"}`).join(","); 462 } 463}; 464var Timer = class _Timer extends Event { 465 constructor() { 466 super(...arguments); 467 this._logger = new Logger(`Timer('${this._name}')`); 468 this._timerHandle = null; 469 this._expiration = 0; 470 this._callback = () => { 471 const diff = this._expiration - _Timer.getEpochTime(); 472 this._logger.debug("timer completes in", diff); 473 if (this._expiration <= _Timer.getEpochTime()) { 474 this.cancel(); 475 void super.raise(); 476 } 477 }; 478 } 479 // get the time 480 static getEpochTime() { 481 return Math.floor(Date.now() / 1e3); 482 } 483 init(durationInSeconds) { 484 const logger2 = this._logger.create("init"); 485 durationInSeconds = Math.max(Math.floor(durationInSeconds), 1); 486 const expiration = _Timer.getEpochTime() + durationInSeconds; 487 if (this.expiration === expiration && this._timerHandle) { 488 logger2.debug("skipping since already initialized for expiration at", this.expiration); 489 return; 490 } 491 this.cancel(); 492 logger2.debug("using duration", durationInSeconds); 493 this._expiration = expiration; 494 const timerDurationInSeconds = Math.min(durationInSeconds, 5); 495 this._timerHandle = setInterval(this._callback, timerDurationInSeconds * 1e3); 496 } 497 get expiration() { 498 return this._expiration; 499 } 500 cancel() { 501 this._logger.create("cancel"); 502 if (this._timerHandle) { 503 clearInterval(this._timerHandle); 504 this._timerHandle = null; 505 } 506 } 507}; 508var UrlUtils = class { 509 static readParams(url, responseMode = "query") { 510 if (!url) throw new TypeError("Invalid URL"); 511 const parsedUrl = new URL(url, "http://127.0.0.1"); 512 const params = parsedUrl[responseMode === "fragment" ? "hash" : "search"]; 513 return new URLSearchParams(params.slice(1)); 514 } 515}; 516var URL_STATE_DELIMITER = ";"; 517var ErrorResponse = class extends Error { 518 constructor(args, form) { 519 var _a, _b, _c; 520 super(args.error_description || args.error || ""); 521 this.form = form; 522 this.name = "ErrorResponse"; 523 if (!args.error) { 524 Logger.error("ErrorResponse", "No error passed"); 525 throw new Error("No error passed"); 526 } 527 this.error = args.error; 528 this.error_description = (_a = args.error_description) != null ? _a : null; 529 this.error_uri = (_b = args.error_uri) != null ? _b : null; 530 this.state = args.userState; 531 this.session_state = (_c = args.session_state) != null ? _c : null; 532 this.url_state = args.url_state; 533 } 534}; 535var ErrorTimeout = class extends Error { 536 constructor(message) { 537 super(message); 538 this.name = "ErrorTimeout"; 539 } 540}; 541var AccessTokenEvents = class { 542 constructor(args) { 543 this._logger = new Logger("AccessTokenEvents"); 544 this._expiringTimer = new Timer("Access token expiring"); 545 this._expiredTimer = new Timer("Access token expired"); 546 this._expiringNotificationTimeInSeconds = args.expiringNotificationTimeInSeconds; 547 } 548 async load(container) { 549 const logger2 = this._logger.create("load"); 550 if (container.access_token && container.expires_in !== void 0) { 551 const duration = container.expires_in; 552 logger2.debug("access token present, remaining duration:", duration); 553 if (duration > 0) { 554 let expiring = duration - this._expiringNotificationTimeInSeconds; 555 if (expiring <= 0) { 556 expiring = 1; 557 } 558 logger2.debug("registering expiring timer, raising in", expiring, "seconds"); 559 this._expiringTimer.init(expiring); 560 } else { 561 logger2.debug("canceling existing expiring timer because we're past expiration."); 562 this._expiringTimer.cancel(); 563 } 564 const expired = duration + 1; 565 logger2.debug("registering expired timer, raising in", expired, "seconds"); 566 this._expiredTimer.init(expired); 567 } else { 568 this._expiringTimer.cancel(); 569 this._expiredTimer.cancel(); 570 } 571 } 572 async unload() { 573 this._logger.debug("unload: canceling existing access token timers"); 574 this._expiringTimer.cancel(); 575 this._expiredTimer.cancel(); 576 } 577 /** 578 * Add callback: Raised prior to the access token expiring. 579 */ 580 addAccessTokenExpiring(cb) { 581 return this._expiringTimer.addHandler(cb); 582 } 583 /** 584 * Remove callback: Raised prior to the access token expiring. 585 */ 586 removeAccessTokenExpiring(cb) { 587 this._expiringTimer.removeHandler(cb); 588 } 589 /** 590 * Add callback: Raised after the access token has expired. 591 */ 592 addAccessTokenExpired(cb) { 593 return this._expiredTimer.addHandler(cb); 594 } 595 /** 596 * Remove callback: Raised after the access token has expired. 597 */ 598 removeAccessTokenExpired(cb) { 599 this._expiredTimer.removeHandler(cb); 600 } 601}; 602var CheckSessionIFrame = class { 603 constructor(_callback, _client_id, url, _intervalInSeconds, _stopOnError) { 604 this._callback = _callback; 605 this._client_id = _client_id; 606 this._intervalInSeconds = _intervalInSeconds; 607 this._stopOnError = _stopOnError; 608 this._logger = new Logger("CheckSessionIFrame"); 609 this._timer = null; 610 this._session_state = null; 611 this._message = (e) => { 612 if (e.origin === this._frame_origin && e.source === this._frame.contentWindow) { 613 if (e.data === "error") { 614 this._logger.error("error message from check session op iframe"); 615 if (this._stopOnError) { 616 this.stop(); 617 } 618 } else if (e.data === "changed") { 619 this._logger.debug("changed message from check session op iframe"); 620 this.stop(); 621 void this._callback(); 622 } else { 623 this._logger.debug(e.data + " message from check session op iframe"); 624 } 625 } 626 }; 627 const parsedUrl = new URL(url); 628 this._frame_origin = parsedUrl.origin; 629 this._frame = window.document.createElement("iframe"); 630 this._frame.style.visibility = "hidden"; 631 this._frame.style.position = "fixed"; 632 this._frame.style.left = "-1000px"; 633 this._frame.style.top = "0"; 634 this._frame.width = "0"; 635 this._frame.height = "0"; 636 this._frame.src = parsedUrl.href; 637 } 638 load() { 639 return new Promise((resolve) => { 640 this._frame.onload = () => { 641 resolve(); 642 }; 643 window.document.body.appendChild(this._frame); 644 window.addEventListener("message", this._message, false); 645 }); 646 } 647 start(session_state) { 648 if (this._session_state === session_state) { 649 return; 650 } 651 this._logger.create("start"); 652 this.stop(); 653 this._session_state = session_state; 654 const send = () => { 655 if (!this._frame.contentWindow || !this._session_state) { 656 return; 657 } 658 this._frame.contentWindow.postMessage(this._client_id + " " + this._session_state, this._frame_origin); 659 }; 660 send(); 661 this._timer = setInterval(send, this._intervalInSeconds * 1e3); 662 } 663 stop() { 664 this._logger.create("stop"); 665 this._session_state = null; 666 if (this._timer) { 667 clearInterval(this._timer); 668 this._timer = null; 669 } 670 } 671}; 672var InMemoryWebStorage = class { 673 constructor() { 674 this._logger = new Logger("InMemoryWebStorage"); 675 this._data = {}; 676 } 677 clear() { 678 this._logger.create("clear"); 679 this._data = {}; 680 } 681 getItem(key) { 682 this._logger.create(`getItem('${key}')`); 683 return this._data[key]; 684 } 685 setItem(key, value) { 686 this._logger.create(`setItem('${key}')`); 687 this._data[key] = value; 688 } 689 removeItem(key) { 690 this._logger.create(`removeItem('${key}')`); 691 delete this._data[key]; 692 } 693 get length() { 694 return Object.getOwnPropertyNames(this._data).length; 695 } 696 key(index) { 697 return Object.getOwnPropertyNames(this._data)[index]; 698 } 699}; 700var ErrorDPoPNonce = class extends Error { 701 constructor(nonce, message) { 702 super(message); 703 this.name = "ErrorDPoPNonce"; 704 this.nonce = nonce; 705 } 706}; 707var JsonService = class { 708 constructor(additionalContentTypes = [], _jwtHandler = null, _extraHeaders = {}) { 709 this._jwtHandler = _jwtHandler; 710 this._extraHeaders = _extraHeaders; 711 this._logger = new Logger("JsonService"); 712 this._contentTypes = []; 713 this._contentTypes.push(...additionalContentTypes, "application/json"); 714 if (_jwtHandler) { 715 this._contentTypes.push("application/jwt"); 716 } 717 } 718 async fetchWithTimeout(input, init = {}) { 719 const { timeoutInSeconds, ...initFetch } = init; 720 if (!timeoutInSeconds) { 721 return await fetch(input, initFetch); 722 } 723 const controller = new AbortController(); 724 const timeoutId = setTimeout(() => controller.abort(), timeoutInSeconds * 1e3); 725 try { 726 const response = await fetch(input, { 727 ...init, 728 signal: controller.signal 729 }); 730 return response; 731 } catch (err) { 732 if (err instanceof DOMException && err.name === "AbortError") { 733 throw new ErrorTimeout("Network timed out"); 734 } 735 throw err; 736 } finally { 737 clearTimeout(timeoutId); 738 } 739 } 740 async getJson(url, { 741 token, 742 credentials, 743 timeoutInSeconds 744 } = {}) { 745 const logger2 = this._logger.create("getJson"); 746 const headers = { 747 "Accept": this._contentTypes.join(", ") 748 }; 749 if (token) { 750 logger2.debug("token passed, setting Authorization header"); 751 headers["Authorization"] = "Bearer " + token; 752 } 753 this._appendExtraHeaders(headers); 754 let response; 755 try { 756 logger2.debug("url:", url); 757 response = await this.fetchWithTimeout(url, { method: "GET", headers, timeoutInSeconds, credentials }); 758 } catch (err) { 759 logger2.error("Network Error"); 760 throw err; 761 } 762 logger2.debug("HTTP response received, status", response.status); 763 const contentType = response.headers.get("Content-Type"); 764 if (contentType && !this._contentTypes.find((item) => contentType.startsWith(item))) { 765 logger2.throw(new Error(`Invalid response Content-Type: ${contentType != null ? contentType : "undefined"}, from URL: ${url}`)); 766 } 767 if (response.ok && this._jwtHandler && (contentType == null ? void 0 : contentType.startsWith("application/jwt"))) { 768 return await this._jwtHandler(await response.text()); 769 } 770 let json; 771 try { 772 json = await response.json(); 773 } catch (err) { 774 logger2.error("Error parsing JSON response", err); 775 if (response.ok) throw err; 776 throw new Error(`${response.statusText} (${response.status})`); 777 } 778 if (!response.ok) { 779 logger2.error("Error from server:", json); 780 if (json.error) { 781 throw new ErrorResponse(json); 782 } 783 throw new Error(`${response.statusText} (${response.status}): ${JSON.stringify(json)}`); 784 } 785 return json; 786 } 787 async postForm(url, { 788 body, 789 basicAuth, 790 timeoutInSeconds, 791 initCredentials, 792 extraHeaders 793 }) { 794 const logger2 = this._logger.create("postForm"); 795 const headers = { 796 "Accept": this._contentTypes.join(", "), 797 "Content-Type": "application/x-www-form-urlencoded", 798 ...extraHeaders 799 }; 800 if (basicAuth !== void 0) { 801 headers["Authorization"] = "Basic " + basicAuth; 802 } 803 this._appendExtraHeaders(headers); 804 let response; 805 try { 806 logger2.debug("url:", url); 807 response = await this.fetchWithTimeout(url, { method: "POST", headers, body, timeoutInSeconds, credentials: initCredentials }); 808 } catch (err) { 809 logger2.error("Network error"); 810 throw err; 811 } 812 logger2.debug("HTTP response received, status", response.status); 813 const contentType = response.headers.get("Content-Type"); 814 if (contentType && !this._contentTypes.find((item) => contentType.startsWith(item))) { 815 throw new Error(`Invalid response Content-Type: ${contentType != null ? contentType : "undefined"}, from URL: ${url}`); 816 } 817 const responseText = await response.text(); 818 let json = {}; 819 if (responseText) { 820 try { 821 json = JSON.parse(responseText); 822 } catch (err) { 823 logger2.error("Error parsing JSON response", err); 824 if (response.ok) throw err; 825 throw new Error(`${response.statusText} (${response.status})`); 826 } 827 } 828 if (!response.ok) { 829 logger2.error("Error from server:", json); 830 if (response.headers.has("dpop-nonce")) { 831 const nonce = response.headers.get("dpop-nonce"); 832 throw new ErrorDPoPNonce(nonce, `${JSON.stringify(json)}`); 833 } 834 if (json.error) { 835 throw new ErrorResponse(json, body); 836 } 837 throw new Error(`${response.statusText} (${response.status}): ${JSON.stringify(json)}`); 838 } 839 return json; 840 } 841 _appendExtraHeaders(headers) { 842 const logger2 = this._logger.create("appendExtraHeaders"); 843 const customKeys = Object.keys(this._extraHeaders); 844 const protectedHeaders = [ 845 "accept", 846 "content-type" 847 ]; 848 const preventOverride = [ 849 "authorization" 850 ]; 851 if (customKeys.length === 0) { 852 return; 853 } 854 customKeys.forEach((headerName) => { 855 if (protectedHeaders.includes(headerName.toLocaleLowerCase())) { 856 logger2.warn("Protected header could not be set", headerName, protectedHeaders); 857 return; 858 } 859 if (preventOverride.includes(headerName.toLocaleLowerCase()) && Object.keys(headers).includes(headerName)) { 860 logger2.warn("Header could not be overridden", headerName, preventOverride); 861 return; 862 } 863 const content = typeof this._extraHeaders[headerName] === "function" ? this._extraHeaders[headerName]() : this._extraHeaders[headerName]; 864 if (content && content !== "") { 865 headers[headerName] = content; 866 } 867 }); 868 } 869}; 870var MetadataService = class { 871 constructor(_settings) { 872 this._settings = _settings; 873 this._logger = new Logger("MetadataService"); 874 this._signingKeys = null; 875 this._metadata = null; 876 this._metadataUrl = this._settings.metadataUrl; 877 this._jsonService = new JsonService( 878 ["application/jwk-set+json"], 879 null, 880 this._settings.extraHeaders 881 ); 882 if (this._settings.signingKeys) { 883 this._logger.debug("using signingKeys from settings"); 884 this._signingKeys = this._settings.signingKeys; 885 } 886 if (this._settings.metadata) { 887 this._logger.debug("using metadata from settings"); 888 this._metadata = this._settings.metadata; 889 } 890 if (this._settings.fetchRequestCredentials) { 891 this._logger.debug("using fetchRequestCredentials from settings"); 892 this._fetchRequestCredentials = this._settings.fetchRequestCredentials; 893 } 894 } 895 resetSigningKeys() { 896 this._signingKeys = null; 897 } 898 async getMetadata() { 899 const logger2 = this._logger.create("getMetadata"); 900 if (this._metadata) { 901 logger2.debug("using cached values"); 902 return this._metadata; 903 } 904 if (!this._metadataUrl) { 905 logger2.throw(new Error("No authority or metadataUrl configured on settings")); 906 throw null; 907 } 908 logger2.debug("getting metadata from", this._metadataUrl); 909 const metadata = await this._jsonService.getJson(this._metadataUrl, { credentials: this._fetchRequestCredentials, timeoutInSeconds: this._settings.requestTimeoutInSeconds }); 910 logger2.debug("merging remote JSON with seed metadata"); 911 this._metadata = Object.assign({}, metadata, this._settings.metadataSeed); 912 return this._metadata; 913 } 914 getIssuer() { 915 return this._getMetadataProperty("issuer"); 916 } 917 getAuthorizationEndpoint() { 918 return this._getMetadataProperty("authorization_endpoint"); 919 } 920 getUserInfoEndpoint() { 921 return this._getMetadataProperty("userinfo_endpoint"); 922 } 923 getTokenEndpoint(optional = true) { 924 return this._getMetadataProperty("token_endpoint", optional); 925 } 926 getCheckSessionIframe() { 927 return this._getMetadataProperty("check_session_iframe", true); 928 } 929 getEndSessionEndpoint() { 930 return this._getMetadataProperty("end_session_endpoint", true); 931 } 932 getRevocationEndpoint(optional = true) { 933 return this._getMetadataProperty("revocation_endpoint", optional); 934 } 935 getKeysEndpoint(optional = true) { 936 return this._getMetadataProperty("jwks_uri", optional); 937 } 938 async _getMetadataProperty(name, optional = false) { 939 const logger2 = this._logger.create(`_getMetadataProperty('${name}')`); 940 const metadata = await this.getMetadata(); 941 logger2.debug("resolved"); 942 if (metadata[name] === void 0) { 943 if (optional === true) { 944 logger2.warn("Metadata does not contain optional property"); 945 return void 0; 946 } 947 logger2.throw(new Error("Metadata does not contain property " + name)); 948 } 949 return metadata[name]; 950 } 951 async getSigningKeys() { 952 const logger2 = this._logger.create("getSigningKeys"); 953 if (this._signingKeys) { 954 logger2.debug("returning signingKeys from cache"); 955 return this._signingKeys; 956 } 957 const jwks_uri = await this.getKeysEndpoint(false); 958 logger2.debug("got jwks_uri", jwks_uri); 959 const keySet = await this._jsonService.getJson(jwks_uri, { timeoutInSeconds: this._settings.requestTimeoutInSeconds }); 960 logger2.debug("got key set", keySet); 961 if (!Array.isArray(keySet.keys)) { 962 logger2.throw(new Error("Missing keys on keyset")); 963 throw null; 964 } 965 this._signingKeys = keySet.keys; 966 return this._signingKeys; 967 } 968}; 969var WebStorageStateStore = class { 970 constructor({ 971 prefix = "oidc.", 972 store = localStorage 973 } = {}) { 974 this._logger = new Logger("WebStorageStateStore"); 975 this._store = store; 976 this._prefix = prefix; 977 } 978 async set(key, value) { 979 this._logger.create(`set('${key}')`); 980 key = this._prefix + key; 981 await this._store.setItem(key, value); 982 } 983 async get(key) { 984 this._logger.create(`get('${key}')`); 985 key = this._prefix + key; 986 const item = await this._store.getItem(key); 987 return item; 988 } 989 async remove(key) { 990 this._logger.create(`remove('${key}')`); 991 key = this._prefix + key; 992 const item = await this._store.getItem(key); 993 await this._store.removeItem(key); 994 return item; 995 } 996 async getAllKeys() { 997 this._logger.create("getAllKeys"); 998 const len = await this._store.length; 999 const keys = []; 1000 for (let index = 0; index < len; index++) { 1001 const key = await this._store.key(index); 1002 if (key && key.indexOf(this._prefix) === 0) { 1003 keys.push(key.substr(this._prefix.length)); 1004 } 1005 } 1006 return keys; 1007 } 1008}; 1009var DefaultResponseType = "code"; 1010var DefaultScope = "openid"; 1011var DefaultClientAuthentication = "client_secret_post"; 1012var DefaultStaleStateAgeInSeconds = 60 * 15; 1013var OidcClientSettingsStore = class { 1014 constructor({ 1015 // metadata related 1016 authority, 1017 metadataUrl, 1018 metadata, 1019 signingKeys, 1020 metadataSeed, 1021 // client related 1022 client_id, 1023 client_secret, 1024 response_type = DefaultResponseType, 1025 scope = DefaultScope, 1026 redirect_uri, 1027 post_logout_redirect_uri, 1028 client_authentication = DefaultClientAuthentication, 1029 token_endpoint_auth_signing_alg = "HS256", 1030 // optional protocol 1031 prompt, 1032 display, 1033 max_age, 1034 ui_locales, 1035 acr_values, 1036 resource, 1037 response_mode, 1038 // behavior flags 1039 filterProtocolClaims = true, 1040 loadUserInfo = false, 1041 requestTimeoutInSeconds, 1042 staleStateAgeInSeconds = DefaultStaleStateAgeInSeconds, 1043 mergeClaimsStrategy = { array: "replace" }, 1044 disablePKCE = false, 1045 // other behavior 1046 stateStore, 1047 revokeTokenAdditionalContentTypes, 1048 fetchRequestCredentials, 1049 refreshTokenAllowedScope, 1050 // extra 1051 extraQueryParams = {}, 1052 extraTokenParams = {}, 1053 extraHeaders = {}, 1054 dpop, 1055 omitScopeWhenRequesting = false 1056 }) { 1057 var _a; 1058 this.authority = authority; 1059 if (metadataUrl) { 1060 this.metadataUrl = metadataUrl; 1061 } else { 1062 this.metadataUrl = authority; 1063 if (authority) { 1064 if (!this.metadataUrl.endsWith("/")) { 1065 this.metadataUrl += "/"; 1066 } 1067 this.metadataUrl += ".well-known/openid-configuration"; 1068 } 1069 } 1070 this.metadata = metadata; 1071 this.metadataSeed = metadataSeed; 1072 this.signingKeys = signingKeys; 1073 this.client_id = client_id; 1074 this.client_secret = client_secret; 1075 this.response_type = response_type; 1076 this.scope = scope; 1077 this.redirect_uri = redirect_uri; 1078 this.post_logout_redirect_uri = post_logout_redirect_uri; 1079 this.client_authentication = client_authentication; 1080 this.token_endpoint_auth_signing_alg = token_endpoint_auth_signing_alg; 1081 this.prompt = prompt; 1082 this.display = display; 1083 this.max_age = max_age; 1084 this.ui_locales = ui_locales; 1085 this.acr_values = acr_values; 1086 this.resource = resource; 1087 this.response_mode = response_mode; 1088 this.filterProtocolClaims = filterProtocolClaims != null ? filterProtocolClaims : true; 1089 this.loadUserInfo = !!loadUserInfo; 1090 this.staleStateAgeInSeconds = staleStateAgeInSeconds; 1091 this.mergeClaimsStrategy = mergeClaimsStrategy; 1092 this.omitScopeWhenRequesting = omitScopeWhenRequesting; 1093 this.disablePKCE = !!disablePKCE; 1094 this.revokeTokenAdditionalContentTypes = revokeTokenAdditionalContentTypes; 1095 this.fetchRequestCredentials = fetchRequestCredentials ? fetchRequestCredentials : "same-origin"; 1096 this.requestTimeoutInSeconds = requestTimeoutInSeconds; 1097 if (stateStore) { 1098 this.stateStore = stateStore; 1099 } else { 1100 const store = typeof window !== "undefined" ? window.localStorage : new InMemoryWebStorage(); 1101 this.stateStore = new WebStorageStateStore({ store }); 1102 } 1103 this.refreshTokenAllowedScope = refreshTokenAllowedScope; 1104 this.extraQueryParams = extraQueryParams; 1105 this.extraTokenParams = extraTokenParams; 1106 this.extraHeaders = extraHeaders; 1107 this.dpop = dpop; 1108 if (this.dpop && !((_a = this.dpop) == null ? void 0 : _a.store)) { 1109 throw new Error("A DPoPStore is required when dpop is enabled"); 1110 } 1111 } 1112}; 1113var UserInfoService = class { 1114 constructor(_settings, _metadataService) { 1115 this._settings = _settings; 1116 this._metadataService = _metadataService; 1117 this._logger = new Logger("UserInfoService"); 1118 this._getClaimsFromJwt = async (responseText) => { 1119 const logger2 = this._logger.create("_getClaimsFromJwt"); 1120 try { 1121 const payload = JwtUtils.decode(responseText); 1122 logger2.debug("JWT decoding successful"); 1123 return payload; 1124 } catch (err) { 1125 logger2.error("Error parsing JWT response"); 1126 throw err; 1127 } 1128 }; 1129 this._jsonService = new JsonService( 1130 void 0, 1131 this._getClaimsFromJwt, 1132 this._settings.extraHeaders 1133 ); 1134 } 1135 async getClaims(token) { 1136 const logger2 = this._logger.create("getClaims"); 1137 if (!token) { 1138 this._logger.throw(new Error("No token passed")); 1139 } 1140 const url = await this._metadataService.getUserInfoEndpoint(); 1141 logger2.debug("got userinfo url", url); 1142 const claims = await this._jsonService.getJson(url, { 1143 token, 1144 credentials: this._settings.fetchRequestCredentials, 1145 timeoutInSeconds: this._settings.requestTimeoutInSeconds 1146 }); 1147 logger2.debug("got claims", claims); 1148 return claims; 1149 } 1150}; 1151var TokenClient = class { 1152 constructor(_settings, _metadataService) { 1153 this._settings = _settings; 1154 this._metadataService = _metadataService; 1155 this._logger = new Logger("TokenClient"); 1156 this._jsonService = new JsonService( 1157 this._settings.revokeTokenAdditionalContentTypes, 1158 null, 1159 this._settings.extraHeaders 1160 ); 1161 } 1162 /** 1163 * Exchange code. 1164 * 1165 * @see https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 1166 */ 1167 async exchangeCode({ 1168 grant_type = "authorization_code", 1169 redirect_uri = this._settings.redirect_uri, 1170 client_id = this._settings.client_id, 1171 client_secret = this._settings.client_secret, 1172 extraHeaders, 1173 ...args 1174 }) { 1175 const logger2 = this._logger.create("exchangeCode"); 1176 if (!client_id) { 1177 logger2.throw(new Error("A client_id is required")); 1178 } 1179 if (!redirect_uri) { 1180 logger2.throw(new Error("A redirect_uri is required")); 1181 } 1182 if (!args.code) { 1183 logger2.throw(new Error("A code is required")); 1184 } 1185 const params = new URLSearchParams({ grant_type, redirect_uri }); 1186 for (const [key, value] of Object.entries(args)) { 1187 if (value != null) { 1188 params.set(key, value); 1189 } 1190 } 1191 if ((this._settings.client_authentication === "client_secret_basic" || this._settings.client_authentication === "client_secret_jwt") && (client_secret === void 0 || client_secret === null)) { 1192 logger2.throw(new Error("A client_secret is required")); 1193 throw null; 1194 } 1195 let basicAuth; 1196 const url = await this._metadataService.getTokenEndpoint(false); 1197 switch (this._settings.client_authentication) { 1198 case "client_secret_basic": 1199 basicAuth = CryptoUtils.generateBasicAuth(client_id, client_secret); 1200 break; 1201 case "client_secret_post": 1202 params.append("client_id", client_id); 1203 if (client_secret) { 1204 params.append("client_secret", client_secret); 1205 } 1206 break; 1207 case "client_secret_jwt": { 1208 const clientAssertion = await CryptoUtils.generateClientAssertionJwt(client_id, client_secret, url, this._settings.token_endpoint_auth_signing_alg); 1209 params.append("client_id", client_id); 1210 params.append("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); 1211 params.append("client_assertion", clientAssertion); 1212 break; 1213 } 1214 } 1215 logger2.debug("got token endpoint"); 1216 const response = await this._jsonService.postForm(url, { 1217 body: params, 1218 basicAuth, 1219 timeoutInSeconds: this._settings.requestTimeoutInSeconds, 1220 initCredentials: this._settings.fetchRequestCredentials, 1221 extraHeaders 1222 }); 1223 logger2.debug("got response"); 1224 return response; 1225 } 1226 /** 1227 * Exchange credentials. 1228 * 1229 * @see https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2 1230 */ 1231 async exchangeCredentials({ 1232 grant_type = "password", 1233 client_id = this._settings.client_id, 1234 client_secret = this._settings.client_secret, 1235 scope = this._settings.scope, 1236 ...args 1237 }) { 1238 const logger2 = this._logger.create("exchangeCredentials"); 1239 if (!client_id) { 1240 logger2.throw(new Error("A client_id is required")); 1241 } 1242 const params = new URLSearchParams({ grant_type }); 1243 if (!this._settings.omitScopeWhenRequesting) { 1244 params.set("scope", scope); 1245 } 1246 for (const [key, value] of Object.entries(args)) { 1247 if (value != null) { 1248 params.set(key, value); 1249 } 1250 } 1251 if ((this._settings.client_authentication === "client_secret_basic" || this._settings.client_authentication === "client_secret_jwt") && (client_secret === void 0 || client_secret === null)) { 1252 logger2.throw(new Error("A client_secret is required")); 1253 throw null; 1254 } 1255 let basicAuth; 1256 const url = await this._metadataService.getTokenEndpoint(false); 1257 switch (this._settings.client_authentication) { 1258 case "client_secret_basic": 1259 basicAuth = CryptoUtils.generateBasicAuth(client_id, client_secret); 1260 break; 1261 case "client_secret_post": 1262 params.append("client_id", client_id); 1263 if (client_secret) { 1264 params.append("client_secret", client_secret); 1265 } 1266 break; 1267 case "client_secret_jwt": { 1268 const clientAssertion = await CryptoUtils.generateClientAssertionJwt(client_id, client_secret, url, this._settings.token_endpoint_auth_signing_alg); 1269 params.append("client_id", client_id); 1270 params.append("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); 1271 params.append("client_assertion", clientAssertion); 1272 break; 1273 } 1274 } 1275 logger2.debug("got token endpoint"); 1276 const response = await this._jsonService.postForm(url, { body: params, basicAuth, timeoutInSeconds: this._settings.requestTimeoutInSeconds, initCredentials: this._settings.fetchRequestCredentials }); 1277 logger2.debug("got response"); 1278 return response; 1279 } 1280 /** 1281 * Exchange a refresh token. 1282 * 1283 * @see https://www.rfc-editor.org/rfc/rfc6749#section-6 1284 */ 1285 async exchangeRefreshToken({ 1286 grant_type = "refresh_token", 1287 client_id = this._settings.client_id, 1288 client_secret = this._settings.client_secret, 1289 timeoutInSeconds, 1290 extraHeaders, 1291 ...args 1292 }) { 1293 const logger2 = this._logger.create("exchangeRefreshToken"); 1294 if (!client_id) { 1295 logger2.throw(new Error("A client_id is required")); 1296 } 1297 if (!args.refresh_token) { 1298 logger2.throw(new Error("A refresh_token is required")); 1299 } 1300 const params = new URLSearchParams({ grant_type }); 1301 for (const [key, value] of Object.entries(args)) { 1302 if (Array.isArray(value)) { 1303 value.forEach((param) => params.append(key, param)); 1304 } else if (value != null) { 1305 params.set(key, value); 1306 } 1307 } 1308 if ((this._settings.client_authentication === "client_secret_basic" || this._settings.client_authentication === "client_secret_jwt") && (client_secret === void 0 || client_secret === null)) { 1309 logger2.throw(new Error("A client_secret is required")); 1310 throw null; 1311 } 1312 let basicAuth; 1313 const url = await this._metadataService.getTokenEndpoint(false); 1314 switch (this._settings.client_authentication) { 1315 case "client_secret_basic": 1316 basicAuth = CryptoUtils.generateBasicAuth(client_id, client_secret); 1317 break; 1318 case "client_secret_post": 1319 params.append("client_id", client_id); 1320 if (client_secret) { 1321 params.append("client_secret", client_secret); 1322 } 1323 break; 1324 case "client_secret_jwt": { 1325 const clientAssertion = await CryptoUtils.generateClientAssertionJwt(client_id, client_secret, url, this._settings.token_endpoint_auth_signing_alg); 1326 params.append("client_id", client_id); 1327 params.append("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); 1328 params.append("client_assertion", clientAssertion); 1329 break; 1330 } 1331 } 1332 logger2.debug("got token endpoint"); 1333 const response = await this._jsonService.postForm(url, { body: params, basicAuth, timeoutInSeconds, initCredentials: this._settings.fetchRequestCredentials, extraHeaders }); 1334 logger2.debug("got response"); 1335 return response; 1336 } 1337 /** 1338 * Revoke an access or refresh token. 1339 * 1340 * @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.1 1341 */ 1342 async revoke(args) { 1343 var _a; 1344 const logger2 = this._logger.create("revoke"); 1345 if (!args.token) { 1346 logger2.throw(new Error("A token is required")); 1347 } 1348 const url = await this._metadataService.getRevocationEndpoint(false); 1349 logger2.debug(`got revocation endpoint, revoking ${(_a = args.token_type_hint) != null ? _a : "default token type"}`); 1350 const params = new URLSearchParams(); 1351 for (const [key, value] of Object.entries(args)) { 1352 if (value != null) { 1353 params.set(key, value); 1354 } 1355 } 1356 params.set("client_id", this._settings.client_id); 1357 if (this._settings.client_secret) { 1358 params.set("client_secret", this._settings.client_secret); 1359 } 1360 await this._jsonService.postForm(url, { body: params, timeoutInSeconds: this._settings.requestTimeoutInSeconds }); 1361 logger2.debug("got response"); 1362 } 1363}; 1364var ResponseValidator = class { 1365 constructor(_settings, _metadataService, _claimsService) { 1366 this._settings = _settings; 1367 this._metadataService = _metadataService; 1368 this._claimsService = _claimsService; 1369 this._logger = new Logger("ResponseValidator"); 1370 this._userInfoService = new UserInfoService(this._settings, this._metadataService); 1371 this._tokenClient = new TokenClient(this._settings, this._metadataService); 1372 } 1373 async validateSigninResponse(response, state, extraHeaders) { 1374 const logger2 = this._logger.create("validateSigninResponse"); 1375 this._processSigninState(response, state); 1376 logger2.debug("state processed"); 1377 await this._processCode(response, state, extraHeaders); 1378 logger2.debug("code processed"); 1379 if (response.isOpenId) { 1380 this._validateIdTokenAttributes(response, "", state.nonce); 1381 } 1382 logger2.debug("tokens validated"); 1383 await this._processClaims(response, state == null ? void 0 : state.skipUserInfo, response.isOpenId); 1384 logger2.debug("claims processed"); 1385 } 1386 async validateCredentialsResponse(response, skipUserInfo) { 1387 const logger2 = this._logger.create("validateCredentialsResponse"); 1388 const shouldValidateSubClaim = response.isOpenId && !!response.id_token; 1389 if (shouldValidateSubClaim) { 1390 this._validateIdTokenAttributes(response); 1391 } 1392 logger2.debug("tokens validated"); 1393 await this._processClaims(response, skipUserInfo, shouldValidateSubClaim); 1394 logger2.debug("claims processed"); 1395 } 1396 async validateRefreshResponse(response, state) { 1397 var _a, _b; 1398 const logger2 = this._logger.create("validateRefreshResponse"); 1399 response.userState = state.data; 1400 (_a = response.session_state) != null ? _a : response.session_state = state.session_state; 1401 (_b = response.scope) != null ? _b : response.scope = state.scope; 1402 if (response.isOpenId && !!response.id_token) { 1403 this._validateIdTokenAttributes(response, state.id_token); 1404 logger2.debug("ID Token validated"); 1405 } 1406 if (!response.id_token) { 1407 response.id_token = state.id_token; 1408 response.profile = state.profile; 1409 } 1410 const hasIdToken = response.isOpenId && !!response.id_token; 1411 await this._processClaims(response, false, hasIdToken); 1412 logger2.debug("claims processed"); 1413 } 1414 validateSignoutResponse(response, state) { 1415 const logger2 = this._logger.create("validateSignoutResponse"); 1416 if (state.id !== response.state) { 1417 logger2.throw(new Error("State does not match")); 1418 } 1419 logger2.debug("state validated"); 1420 response.userState = state.data; 1421 if (response.error) { 1422 logger2.warn("Response was error", response.error); 1423 throw new ErrorResponse(response); 1424 } 1425 } 1426 _processSigninState(response, state) { 1427 var _a; 1428 const logger2 = this._logger.create("_processSigninState"); 1429 if (state.id !== response.state) { 1430 logger2.throw(new Error("State does not match")); 1431 } 1432 if (!state.client_id) { 1433 logger2.throw(new Error("No client_id on state")); 1434 } 1435 if (!state.authority) { 1436 logger2.throw(new Error("No authority on state")); 1437 } 1438 if (this._settings.authority !== state.authority) { 1439 logger2.throw(new Error("authority mismatch on settings vs. signin state")); 1440 } 1441 if (this._settings.client_id && this._settings.client_id !== state.client_id) { 1442 logger2.throw(new Error("client_id mismatch on settings vs. signin state")); 1443 } 1444 logger2.debug("state validated"); 1445 response.userState = state.data; 1446 response.url_state = state.url_state; 1447 (_a = response.scope) != null ? _a : response.scope = state.scope; 1448 if (response.error) { 1449 logger2.warn("Response was error", response.error); 1450 throw new ErrorResponse(response); 1451 } 1452 if (state.code_verifier && !response.code) { 1453 logger2.throw(new Error("Expected code in response")); 1454 } 1455 } 1456 async _processClaims(response, skipUserInfo = false, validateSub = true) { 1457 const logger2 = this._logger.create("_processClaims"); 1458 response.profile = this._claimsService.filterProtocolClaims(response.profile); 1459 if (skipUserInfo || !this._settings.loadUserInfo || !response.access_token) { 1460 logger2.debug("not loading user info"); 1461 return; 1462 } 1463 logger2.debug("loading user info"); 1464 const claims = await this._userInfoService.getClaims(response.access_token); 1465 logger2.debug("user info claims received from user info endpoint"); 1466 if (validateSub && claims.sub !== response.profile.sub) { 1467 logger2.throw(new Error("subject from UserInfo response does not match subject in ID Token")); 1468 } 1469 response.profile = this._claimsService.mergeClaims(response.profile, this._claimsService.filterProtocolClaims(claims)); 1470 logger2.debug("user info claims received, updated profile:", response.profile); 1471 } 1472 async _processCode(response, state, extraHeaders) { 1473 const logger2 = this._logger.create("_processCode"); 1474 if (response.code) { 1475 logger2.debug("Validating code"); 1476 const tokenResponse = await this._tokenClient.exchangeCode({ 1477 client_id: state.client_id, 1478 client_secret: state.client_secret, 1479 code: response.code, 1480 redirect_uri: state.redirect_uri, 1481 code_verifier: state.code_verifier, 1482 extraHeaders, 1483 ...state.extraTokenParams 1484 }); 1485 Object.assign(response, tokenResponse); 1486 } else { 1487 logger2.debug("No code to process"); 1488 } 1489 } 1490 _validateIdTokenAttributes(response, existingToken, nonce) { 1491 var _a; 1492 const logger2 = this._logger.create("_validateIdTokenAttributes"); 1493 logger2.debug("decoding ID Token JWT"); 1494 const incoming = JwtUtils.decode((_a = response.id_token) != null ? _a : ""); 1495 if (!incoming.sub) { 1496 logger2.throw(new Error("ID Token is missing a subject claim")); 1497 } 1498 if (nonce && incoming.nonce !== nonce) { 1499 logger2.throw(new Error("nonce in id_token does not match nonce in client storage")); 1500 } 1501 if (existingToken) { 1502 const existing = JwtUtils.decode(existingToken); 1503 if (incoming.sub !== existing.sub) { 1504 logger2.throw(new Error("sub in id_token does not match current sub")); 1505 } 1506 if (incoming.auth_time && incoming.auth_time !== existing.auth_time) { 1507 logger2.throw(new Error("auth_time in id_token does not match original auth_time")); 1508 } 1509 if (incoming.azp && incoming.azp !== existing.azp) { 1510 logger2.throw(new Error("azp in id_token does not match original azp")); 1511 } 1512 if (!incoming.azp && existing.azp) { 1513 logger2.throw(new Error("azp not in id_token, but present in original id_token")); 1514 } 1515 } 1516 response.profile = incoming; 1517 } 1518}; 1519var State = class _State { 1520 constructor(args) { 1521 this.id = args.id || CryptoUtils.generateUUIDv4(); 1522 this.data = args.data; 1523 if (args.created && args.created > 0) { 1524 this.created = args.created; 1525 } else { 1526 this.created = Timer.getEpochTime(); 1527 } 1528 this.request_type = args.request_type; 1529 this.url_state = args.url_state; 1530 } 1531 toStorageString() { 1532 new Logger("State").create("toStorageString"); 1533 return JSON.stringify({ 1534 id: this.id, 1535 data: this.data, 1536 created: this.created, 1537 request_type: this.request_type, 1538 url_state: this.url_state 1539 }); 1540 } 1541 static fromStorageString(storageString) { 1542 Logger.createStatic("State", "fromStorageString"); 1543 return Promise.resolve(new _State(JSON.parse(storageString))); 1544 } 1545 static async clearStaleState(storage, age) { 1546 const logger2 = Logger.createStatic("State", "clearStaleState"); 1547 const cutoff = Timer.getEpochTime() - age; 1548 const keys = await storage.getAllKeys(); 1549 logger2.debug("got keys", keys); 1550 for (let i = 0; i < keys.length; i++) { 1551 const key = keys[i]; 1552 const item = await storage.get(key); 1553 let remove = false; 1554 if (item) { 1555 try { 1556 const state = await _State.fromStorageString(item); 1557 logger2.debug("got item from key:", key, state.created); 1558 if (state.created <= cutoff) { 1559 remove = true; 1560 } 1561 } catch (err) { 1562 logger2.error("Error parsing state for key:", key, err); 1563 remove = true; 1564 } 1565 } else { 1566 logger2.debug("no item in storage for key:", key); 1567 remove = true; 1568 } 1569 if (remove) { 1570 logger2.debug("removed item for key:", key); 1571 void storage.remove(key); 1572 } 1573 } 1574 } 1575}; 1576var SigninState = class _SigninState extends State { 1577 constructor(args) { 1578 super(args); 1579 this.code_verifier = args.code_verifier; 1580 this.code_challenge = args.code_challenge; 1581 this.authority = args.authority; 1582 this.client_id = args.client_id; 1583 this.redirect_uri = args.redirect_uri; 1584 this.scope = args.scope; 1585 this.client_secret = args.client_secret; 1586 this.extraTokenParams = args.extraTokenParams; 1587 this.response_mode = args.response_mode; 1588 this.skipUserInfo = args.skipUserInfo; 1589 this.nonce = args.nonce; 1590 } 1591 static async create(args) { 1592 const code_verifier = args.code_verifier === true ? CryptoUtils.generateCodeVerifier() : args.code_verifier || void 0; 1593 const code_challenge = code_verifier ? await CryptoUtils.generateCodeChallenge(code_verifier) : void 0; 1594 return new _SigninState({ 1595 ...args, 1596 code_verifier, 1597 code_challenge 1598 }); 1599 } 1600 toStorageString() { 1601 new Logger("SigninState").create("toStorageString"); 1602 return JSON.stringify({ 1603 id: this.id, 1604 data: this.data, 1605 created: this.created, 1606 request_type: this.request_type, 1607 url_state: this.url_state, 1608 code_verifier: this.code_verifier, 1609 authority: this.authority, 1610 client_id: this.client_id, 1611 redirect_uri: this.redirect_uri, 1612 scope: this.scope, 1613 client_secret: this.client_secret, 1614 extraTokenParams: this.extraTokenParams, 1615 response_mode: this.response_mode, 1616 skipUserInfo: this.skipUserInfo, 1617 nonce: this.nonce 1618 }); 1619 } 1620 static fromStorageString(storageString) { 1621 Logger.createStatic("SigninState", "fromStorageString"); 1622 const data = JSON.parse(storageString); 1623 return _SigninState.create(data); 1624 } 1625}; 1626var _SigninRequest = class _SigninRequest2 { 1627 constructor(args) { 1628 this.url = args.url; 1629 this.state = args.state; 1630 } 1631 static async create({ 1632 // mandatory 1633 url, 1634 authority, 1635 client_id, 1636 redirect_uri, 1637 response_type, 1638 scope, 1639 // optional 1640 state_data, 1641 response_mode, 1642 request_type, 1643 client_secret, 1644 nonce, 1645 url_state, 1646 resource, 1647 skipUserInfo, 1648 extraQueryParams, 1649 extraTokenParams, 1650 disablePKCE, 1651 dpopJkt, 1652 omitScopeWhenRequesting, 1653 ...optionalParams 1654 }) { 1655 if (!url) { 1656 this._logger.error("create: No url passed"); 1657 throw new Error("url"); 1658 } 1659 if (!client_id) { 1660 this._logger.error("create: No client_id passed"); 1661 throw new Error("client_id"); 1662 } 1663 if (!redirect_uri) { 1664 this._logger.error("create: No redirect_uri passed"); 1665 throw new Error("redirect_uri"); 1666 } 1667 if (!response_type) { 1668 this._logger.error("create: No response_type passed"); 1669 throw new Error("response_type"); 1670 } 1671 if (!scope) { 1672 this._logger.error("create: No scope passed"); 1673 throw new Error("scope"); 1674 } 1675 if (!authority) { 1676 this._logger.error("create: No authority passed"); 1677 throw new Error("authority"); 1678 } 1679 const state = await SigninState.create({ 1680 data: state_data, 1681 request_type, 1682 url_state, 1683 code_verifier: !disablePKCE, 1684 client_id, 1685 authority, 1686 redirect_uri, 1687 response_mode, 1688 client_secret, 1689 scope, 1690 extraTokenParams, 1691 skipUserInfo, 1692 nonce 1693 }); 1694 const parsedUrl = new URL(url); 1695 parsedUrl.searchParams.append("client_id", client_id); 1696 parsedUrl.searchParams.append("redirect_uri", redirect_uri); 1697 parsedUrl.searchParams.append("response_type", response_type); 1698 if (!omitScopeWhenRequesting) { 1699 parsedUrl.searchParams.append("scope", scope); 1700 } 1701 if (nonce) { 1702 parsedUrl.searchParams.append("nonce", nonce); 1703 } 1704 if (dpopJkt) { 1705 parsedUrl.searchParams.append("dpop_jkt", dpopJkt); 1706 } 1707 let stateParam = state.id; 1708 if (url_state) { 1709 stateParam = `${stateParam}${URL_STATE_DELIMITER}${url_state}`; 1710 } 1711 parsedUrl.searchParams.append("state", stateParam); 1712 if (state.code_challenge) { 1713 parsedUrl.searchParams.append("code_challenge", state.code_challenge); 1714 parsedUrl.searchParams.append("code_challenge_method", "S256"); 1715 } 1716 if (resource) { 1717 const resources = Array.isArray(resource) ? resource : [resource]; 1718 resources.forEach((r) => parsedUrl.searchParams.append("resource", r)); 1719 } 1720 for (const [key, value] of Object.entries({ response_mode, ...optionalParams, ...extraQueryParams })) { 1721 if (value != null) { 1722 parsedUrl.searchParams.append(key, value.toString()); 1723 } 1724 } 1725 return new _SigninRequest2({ 1726 url: parsedUrl.href, 1727 state 1728 }); 1729 } 1730}; 1731_SigninRequest._logger = new Logger("SigninRequest"); 1732var SigninRequest = _SigninRequest; 1733var OidcScope = "openid"; 1734var SigninResponse = class { 1735 constructor(params) { 1736 this.access_token = ""; 1737 this.token_type = ""; 1738 this.profile = {}; 1739 this.state = params.get("state"); 1740 this.session_state = params.get("session_state"); 1741 if (this.state) { 1742 const splitState = decodeURIComponent(this.state).split(URL_STATE_DELIMITER); 1743 this.state = splitState[0]; 1744 if (splitState.length > 1) { 1745 this.url_state = splitState.slice(1).join(URL_STATE_DELIMITER); 1746 } 1747 } 1748 this.error = params.get("error"); 1749 this.error_description = params.get("error_description"); 1750 this.error_uri = params.get("error_uri"); 1751 this.code = params.get("code"); 1752 } 1753 get expires_in() { 1754 if (this.expires_at === void 0) { 1755 return void 0; 1756 } 1757 return this.expires_at - Timer.getEpochTime(); 1758 } 1759 set expires_in(value) { 1760 if (typeof value === "string") value = Number(value); 1761 if (value !== void 0 && value >= 0) { 1762 this.expires_at = Math.floor(value) + Timer.getEpochTime(); 1763 } 1764 } 1765 get isOpenId() { 1766 var _a; 1767 return ((_a = this.scope) == null ? void 0 : _a.split(" ").includes(OidcScope)) || !!this.id_token; 1768 } 1769}; 1770var SignoutRequest = class { 1771 constructor({ 1772 url, 1773 state_data, 1774 id_token_hint, 1775 post_logout_redirect_uri, 1776 extraQueryParams, 1777 request_type, 1778 client_id, 1779 url_state 1780 }) { 1781 this._logger = new Logger("SignoutRequest"); 1782 if (!url) { 1783 this._logger.error("ctor: No url passed"); 1784 throw new Error("url"); 1785 } 1786 const parsedUrl = new URL(url); 1787 if (id_token_hint) { 1788 parsedUrl.searchParams.append("id_token_hint", id_token_hint); 1789 } 1790 if (client_id) { 1791 parsedUrl.searchParams.append("client_id", client_id); 1792 } 1793 if (post_logout_redirect_uri) { 1794 parsedUrl.searchParams.append("post_logout_redirect_uri", post_logout_redirect_uri); 1795 if (state_data || url_state) { 1796 this.state = new State({ data: state_data, request_type, url_state }); 1797 let stateParam = this.state.id; 1798 if (url_state) { 1799 stateParam = `${stateParam}${URL_STATE_DELIMITER}${url_state}`; 1800 } 1801 parsedUrl.searchParams.append("state", stateParam); 1802 } 1803 } 1804 for (const [key, value] of Object.entries({ ...extraQueryParams })) { 1805 if (value != null) { 1806 parsedUrl.searchParams.append(key, value.toString()); 1807 } 1808 } 1809 this.url = parsedUrl.href; 1810 } 1811}; 1812var SignoutResponse = class { 1813 constructor(params) { 1814 this.state = params.get("state"); 1815 if (this.state) { 1816 const splitState = decodeURIComponent(this.state).split(URL_STATE_DELIMITER); 1817 this.state = splitState[0]; 1818 if (splitState.length > 1) { 1819 this.url_state = splitState.slice(1).join(URL_STATE_DELIMITER); 1820 } 1821 } 1822 this.error = params.get("error"); 1823 this.error_description = params.get("error_description"); 1824 this.error_uri = params.get("error_uri"); 1825 } 1826}; 1827var DefaultProtocolClaims = [ 1828 "nbf", 1829 "jti", 1830 "auth_time", 1831 "nonce", 1832 "acr", 1833 "amr", 1834 "azp", 1835 "at_hash" 1836 // https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken 1837]; 1838var InternalRequiredProtocolClaims = ["sub", "iss", "aud", "exp", "iat"]; 1839var ClaimsService = class { 1840 constructor(_settings) { 1841 this._settings = _settings; 1842 this._logger = new Logger("ClaimsService"); 1843 } 1844 filterProtocolClaims(claims) { 1845 const result = { ...claims }; 1846 if (this._settings.filterProtocolClaims) { 1847 let protocolClaims; 1848 if (Array.isArray(this._settings.filterProtocolClaims)) { 1849 protocolClaims = this._settings.filterProtocolClaims; 1850 } else { 1851 protocolClaims = DefaultProtocolClaims; 1852 } 1853 for (const claim of protocolClaims) { 1854 if (!InternalRequiredProtocolClaims.includes(claim)) { 1855 delete result[claim]; 1856 } 1857 } 1858 } 1859 return result; 1860 } 1861 mergeClaims(claims1, claims2) { 1862 const result = { ...claims1 }; 1863 for (const [claim, values] of Object.entries(claims2)) { 1864 if (result[claim] !== values) { 1865 if (Array.isArray(result[claim]) || Array.isArray(values)) { 1866 if (this._settings.mergeClaimsStrategy.array == "replace") { 1867 result[claim] = values; 1868 } else { 1869 const mergedValues = Array.isArray(result[claim]) ? result[claim] : [result[claim]]; 1870 for (const value of Array.isArray(values) ? values : [values]) { 1871 if (!mergedValues.includes(value)) { 1872 mergedValues.push(value); 1873 } 1874 } 1875 result[claim] = mergedValues; 1876 } 1877 } else if (typeof result[claim] === "object" && typeof values === "object") { 1878 result[claim] = this.mergeClaims(result[claim], values); 1879 } else { 1880 result[claim] = values; 1881 } 1882 } 1883 } 1884 return result; 1885 } 1886}; 1887var DPoPState = class { 1888 constructor(keys, nonce) { 1889 this.keys = keys; 1890 this.nonce = nonce; 1891 } 1892}; 1893var OidcClient = class { 1894 constructor(settings, metadataService) { 1895 this._logger = new Logger("OidcClient"); 1896 this.settings = settings instanceof OidcClientSettingsStore ? settings : new OidcClientSettingsStore(settings); 1897 this.metadataService = metadataService != null ? metadataService : new MetadataService(this.settings); 1898 this._claimsService = new ClaimsService(this.settings); 1899 this._validator = new ResponseValidator(this.settings, this.metadataService, this._claimsService); 1900 this._tokenClient = new TokenClient(this.settings, this.metadataService); 1901 } 1902 async createSigninRequest({ 1903 state, 1904 request, 1905 request_uri, 1906 request_type, 1907 id_token_hint, 1908 login_hint, 1909 skipUserInfo, 1910 nonce, 1911 url_state, 1912 response_type = this.settings.response_type, 1913 scope = this.settings.scope, 1914 redirect_uri = this.settings.redirect_uri, 1915 prompt = this.settings.prompt, 1916 display = this.settings.display, 1917 max_age = this.settings.max_age, 1918 ui_locales = this.settings.ui_locales, 1919 acr_values = this.settings.acr_values, 1920 resource = this.settings.resource, 1921 response_mode = this.settings.response_mode, 1922 extraQueryParams = this.settings.extraQueryParams, 1923 extraTokenParams = this.settings.extraTokenParams, 1924 dpopJkt, 1925 omitScopeWhenRequesting = this.settings.omitScopeWhenRequesting 1926 }) { 1927 const logger2 = this._logger.create("createSigninRequest"); 1928 if (response_type !== "code") { 1929 throw new Error("Only the Authorization Code flow (with PKCE) is supported"); 1930 } 1931 const url = await this.metadataService.getAuthorizationEndpoint(); 1932 logger2.debug("Received authorization endpoint", url); 1933 const signinRequest = await SigninRequest.create({ 1934 url, 1935 authority: this.settings.authority, 1936 client_id: this.settings.client_id, 1937 redirect_uri, 1938 response_type, 1939 scope, 1940 state_data: state, 1941 url_state, 1942 prompt, 1943 display, 1944 max_age, 1945 ui_locales, 1946 id_token_hint, 1947 login_hint, 1948 acr_values, 1949 dpopJkt, 1950 resource, 1951 request, 1952 request_uri, 1953 extraQueryParams, 1954 extraTokenParams, 1955 request_type, 1956 response_mode, 1957 client_secret: this.settings.client_secret, 1958 skipUserInfo, 1959 nonce, 1960 disablePKCE: this.settings.disablePKCE, 1961 omitScopeWhenRequesting 1962 }); 1963 await this.clearStaleState(); 1964 const signinState = signinRequest.state; 1965 await this.settings.stateStore.set(signinState.id, signinState.toStorageString()); 1966 return signinRequest; 1967 } 1968 async readSigninResponseState(url, removeState = false) { 1969 const logger2 = this._logger.create("readSigninResponseState"); 1970 const response = new SigninResponse(UrlUtils.readParams(url, this.settings.response_mode)); 1971 if (!response.state) { 1972 logger2.throw(new Error("No state in response")); 1973 throw null; 1974 } 1975 const storedStateString = await this.settings.stateStore[removeState ? "remove" : "get"](response.state); 1976 if (!storedStateString) { 1977 logger2.throw(new Error("No matching state found in storage")); 1978 throw null; 1979 } 1980 const state = await SigninState.fromStorageString(storedStateString); 1981 return { state, response }; 1982 } 1983 async processSigninResponse(url, extraHeaders, removeState = true) { 1984 const logger2 = this._logger.create("processSigninResponse"); 1985 const { state, response } = await this.readSigninResponseState(url, removeState); 1986 logger2.debug("received state from storage; validating response"); 1987 if (this.settings.dpop && this.settings.dpop.store) { 1988 const dpopProof = await this.getDpopProof(this.settings.dpop.store); 1989 extraHeaders = { ...extraHeaders, "DPoP": dpopProof }; 1990 } 1991 try { 1992 await this._validator.validateSigninResponse(response, state, extraHeaders); 1993 } catch (err) { 1994 if (err instanceof ErrorDPoPNonce && this.settings.dpop) { 1995 const dpopProof = await this.getDpopProof(this.settings.dpop.store, err.nonce); 1996 extraHeaders["DPoP"] = dpopProof; 1997 await this._validator.validateSigninResponse(response, state, extraHeaders); 1998 } else { 1999 throw err; 2000 } 2001 } 2002 return response; 2003 } 2004 async getDpopProof(dpopStore, nonce) { 2005 let keyPair; 2006 let dpopState; 2007 if (!(await dpopStore.getAllKeys()).includes(this.settings.client_id)) { 2008 keyPair = await CryptoUtils.generateDPoPKeys(); 2009 dpopState = new DPoPState(keyPair, nonce); 2010 await dpopStore.set(this.settings.client_id, dpopState); 2011 } else { 2012 dpopState = await dpopStore.get(this.settings.client_id); 2013 if (dpopState.nonce !== nonce && nonce) { 2014 dpopState.nonce = nonce; 2015 await dpopStore.set(this.settings.client_id, dpopState); 2016 } 2017 } 2018 return await CryptoUtils.generateDPoPProof({ 2019 url: await this.metadataService.getTokenEndpoint(false), 2020 httpMethod: "POST", 2021 keyPair: dpopState.keys, 2022 nonce: dpopState.nonce 2023 }); 2024 } 2025 async processResourceOwnerPasswordCredentials({ 2026 username, 2027 password, 2028 skipUserInfo = false, 2029 extraTokenParams = {} 2030 }) { 2031 const tokenResponse = await this._tokenClient.exchangeCredentials({ username, password, ...extraTokenParams }); 2032 const signinResponse = new SigninResponse(new URLSearchParams()); 2033 Object.assign(signinResponse, tokenResponse); 2034 await this._validator.validateCredentialsResponse(signinResponse, skipUserInfo); 2035 return signinResponse; 2036 } 2037 async useRefreshToken({ 2038 state, 2039 redirect_uri, 2040 resource, 2041 timeoutInSeconds, 2042 extraHeaders, 2043 extraTokenParams 2044 }) { 2045 var _a; 2046 const logger2 = this._logger.create("useRefreshToken"); 2047 let scope; 2048 if (this.settings.refreshTokenAllowedScope === void 0) { 2049 scope = state.scope; 2050 } else { 2051 const allowableScopes = this.settings.refreshTokenAllowedScope.split(" "); 2052 const providedScopes = ((_a = state.scope) == null ? void 0 : _a.split(" ")) || []; 2053 scope = providedScopes.filter((s) => allowableScopes.includes(s)).join(" "); 2054 } 2055 if (this.settings.dpop && this.settings.dpop.store) { 2056 const dpopProof = await this.getDpopProof(this.settings.dpop.store); 2057 extraHeaders = { ...extraHeaders, "DPoP": dpopProof }; 2058 } 2059 let result; 2060 try { 2061 result = await this._tokenClient.exchangeRefreshToken({ 2062 refresh_token: state.refresh_token, 2063 // provide the (possible filtered) scope list 2064 scope, 2065 redirect_uri, 2066 resource, 2067 timeoutInSeconds, 2068 extraHeaders, 2069 ...extraTokenParams 2070 }); 2071 } catch (err) { 2072 if (err instanceof ErrorDPoPNonce && this.settings.dpop) { 2073 extraHeaders["DPoP"] = await this.getDpopProof(this.settings.dpop.store, err.nonce); 2074 result = await this._tokenClient.exchangeRefreshToken({ 2075 refresh_token: state.refresh_token, 2076 // provide the (possible filtered) scope list 2077 scope, 2078 redirect_uri, 2079 resource, 2080 timeoutInSeconds, 2081 extraHeaders, 2082 ...extraTokenParams 2083 }); 2084 } else { 2085 throw err; 2086 } 2087 } 2088 const response = new SigninResponse(new URLSearchParams()); 2089 Object.assign(response, result); 2090 logger2.debug("validating response", response); 2091 await this._validator.validateRefreshResponse(response, { 2092 ...state, 2093 // override the scope in the state handed over to the validator 2094 // so it can set the granted scope to the requested scope in case none is included in the response 2095 scope 2096 }); 2097 return response; 2098 } 2099 async createSignoutRequest({ 2100 state, 2101 id_token_hint, 2102 client_id, 2103 request_type, 2104 url_state, 2105 post_logout_redirect_uri = this.settings.post_logout_redirect_uri, 2106 extraQueryParams = this.settings.extraQueryParams 2107 } = {}) { 2108 const logger2 = this._logger.create("createSignoutRequest"); 2109 const url = await this.metadataService.getEndSessionEndpoint(); 2110 if (!url) { 2111 logger2.throw(new Error("No end session endpoint")); 2112 throw null; 2113 } 2114 logger2.debug("Received end session endpoint", url); 2115 if (!client_id && post_logout_redirect_uri && !id_token_hint) { 2116 client_id = this.settings.client_id; 2117 } 2118 const request = new SignoutRequest({ 2119 url, 2120 id_token_hint, 2121 client_id, 2122 post_logout_redirect_uri, 2123 state_data: state, 2124 extraQueryParams, 2125 request_type, 2126 url_state 2127 }); 2128 await this.clearStaleState(); 2129 const signoutState = request.state; 2130 if (signoutState) { 2131 logger2.debug("Signout request has state to persist"); 2132 await this.settings.stateStore.set(signoutState.id, signoutState.toStorageString()); 2133 } 2134 return request; 2135 } 2136 async readSignoutResponseState(url, removeState = false) { 2137 const logger2 = this._logger.create("readSignoutResponseState"); 2138 const response = new SignoutResponse(UrlUtils.readParams(url, this.settings.response_mode)); 2139 if (!response.state) { 2140 logger2.debug("No state in response"); 2141 if (response.error) { 2142 logger2.warn("Response was error:", response.error); 2143 throw new ErrorResponse(response); 2144 } 2145 return { state: void 0, response }; 2146 } 2147 const storedStateString = await this.settings.stateStore[removeState ? "remove" : "get"](response.state); 2148 if (!storedStateString) { 2149 logger2.throw(new Error("No matching state found in storage")); 2150 throw null; 2151 } 2152 const state = await State.fromStorageString(storedStateString); 2153 return { state, response }; 2154 } 2155 async processSignoutResponse(url) { 2156 const logger2 = this._logger.create("processSignoutResponse"); 2157 const { state, response } = await this.readSignoutResponseState(url, true); 2158 if (state) { 2159 logger2.debug("Received state from storage; validating response"); 2160 this._validator.validateSignoutResponse(response, state); 2161 } else { 2162 logger2.debug("No state from storage; skipping response validation"); 2163 } 2164 return response; 2165 } 2166 clearStaleState() { 2167 this._logger.create("clearStaleState"); 2168 return State.clearStaleState(this.settings.stateStore, this.settings.staleStateAgeInSeconds); 2169 } 2170 async revokeToken(token, type) { 2171 this._logger.create("revokeToken"); 2172 return await this._tokenClient.revoke({ 2173 token, 2174 token_type_hint: type 2175 }); 2176 } 2177}; 2178var SessionMonitor = class { 2179 constructor(_userManager) { 2180 this._userManager = _userManager; 2181 this._logger = new Logger("SessionMonitor"); 2182 this._start = async (user) => { 2183 const session_state = user.session_state; 2184 if (!session_state) { 2185 return; 2186 } 2187 const logger2 = this._logger.create("_start"); 2188 if (user.profile) { 2189 this._sub = user.profile.sub; 2190 logger2.debug("session_state", session_state, ", sub", this._sub); 2191 } else { 2192 this._sub = void 0; 2193 logger2.debug("session_state", session_state, ", anonymous user"); 2194 } 2195 if (this._checkSessionIFrame) { 2196 this._checkSessionIFrame.start(session_state); 2197 return; 2198 } 2199 try { 2200 const url = await this._userManager.metadataService.getCheckSessionIframe(); 2201 if (url) { 2202 logger2.debug("initializing check session iframe"); 2203 const client_id = this._userManager.settings.client_id; 2204 const intervalInSeconds = this._userManager.settings.checkSessionIntervalInSeconds; 2205 const stopOnError = this._userManager.settings.stopCheckSessionOnError; 2206 const checkSessionIFrame = new CheckSessionIFrame(this._callback, client_id, url, intervalInSeconds, stopOnError); 2207 await checkSessionIFrame.load(); 2208 this._checkSessionIFrame = checkSessionIFrame; 2209 checkSessionIFrame.start(session_state); 2210 } else { 2211 logger2.warn("no check session iframe found in the metadata"); 2212 } 2213 } catch (err) { 2214 logger2.error("Error from getCheckSessionIframe:", err instanceof Error ? err.message : err); 2215 } 2216 }; 2217 this._stop = () => { 2218 const logger2 = this._logger.create("_stop"); 2219 this._sub = void 0; 2220 if (this._checkSessionIFrame) { 2221 this._checkSessionIFrame.stop(); 2222 } 2223 if (this._userManager.settings.monitorAnonymousSession) { 2224 const timerHandle = setInterval(async () => { 2225 clearInterval(timerHandle); 2226 try { 2227 const session = await this._userManager.querySessionStatus(); 2228 if (session) { 2229 const tmpUser = { 2230 session_state: session.session_state, 2231 profile: session.sub ? { 2232 sub: session.sub 2233 } : null 2234 }; 2235 void this._start(tmpUser); 2236 } 2237 } catch (err) { 2238 logger2.error("error from querySessionStatus", err instanceof Error ? err.message : err); 2239 } 2240 }, 1e3); 2241 } 2242 }; 2243 this._callback = async () => { 2244 const logger2 = this._logger.create("_callback"); 2245 try { 2246 const session = await this._userManager.querySessionStatus(); 2247 let raiseEvent = true; 2248 if (session && this._checkSessionIFrame) { 2249 if (session.sub === this._sub) { 2250 raiseEvent = false; 2251 this._checkSessionIFrame.start(session.session_state); 2252 logger2.debug("same sub still logged in at OP, session state has changed, restarting check session iframe; session_state", session.session_state); 2253 await this._userManager.events._raiseUserSessionChanged(); 2254 } else { 2255 logger2.debug("different subject signed into OP", session.sub); 2256 } 2257 } else { 2258 logger2.debug("subject no longer signed into OP"); 2259 } 2260 if (raiseEvent) { 2261 if (this._sub) { 2262 await this._userManager.events._raiseUserSignedOut(); 2263 } else { 2264 await this._userManager.events._raiseUserSignedIn(); 2265 } 2266 } else { 2267 logger2.debug("no change in session detected, no event to raise"); 2268 } 2269 } catch (err) { 2270 if (this._sub) { 2271 logger2.debug("Error calling queryCurrentSigninSession; raising signed out event", err); 2272 await this._userManager.events._raiseUserSignedOut(); 2273 } 2274 } 2275 }; 2276 if (!_userManager) { 2277 this._logger.throw(new Error("No user manager passed")); 2278 } 2279 this._userManager.events.addUserLoaded(this._start); 2280 this._userManager.events.addUserUnloaded(this._stop); 2281 this._init().catch((err) => { 2282 this._logger.error(err); 2283 }); 2284 } 2285 async _init() { 2286 this._logger.create("_init"); 2287 const user = await this._userManager.getUser(); 2288 if (user) { 2289 void this._start(user); 2290 } else if (this._userManager.settings.monitorAnonymousSession) { 2291 const session = await this._userManager.querySessionStatus(); 2292 if (session) { 2293 const tmpUser = { 2294 session_state: session.session_state, 2295 profile: session.sub ? { 2296 sub: session.sub 2297 } : null 2298 }; 2299 void this._start(tmpUser); 2300 } 2301 } 2302 } 2303}; 2304var User = class _User { 2305 constructor(args) { 2306 var _a; 2307 this.id_token = args.id_token; 2308 this.session_state = (_a = args.session_state) != null ? _a : null; 2309 this.access_token = args.access_token; 2310 this.refresh_token = args.refresh_token; 2311 this.token_type = args.token_type; 2312 this.scope = args.scope; 2313 this.profile = args.profile; 2314 this.expires_at = args.expires_at; 2315 this.state = args.userState; 2316 this.url_state = args.url_state; 2317 } 2318 /** Computed number of seconds the access token has remaining. */ 2319 get expires_in() { 2320 if (this.expires_at === void 0) { 2321 return void 0; 2322 } 2323 return this.expires_at - Timer.getEpochTime(); 2324 } 2325 set expires_in(value) { 2326 if (value !== void 0) { 2327 this.expires_at = Math.floor(value) + Timer.getEpochTime(); 2328 } 2329 } 2330 /** Computed value indicating if the access token is expired. */ 2331 get expired() { 2332 const expires_in = this.expires_in; 2333 if (expires_in === void 0) { 2334 return void 0; 2335 } 2336 return expires_in <= 0; 2337 } 2338 /** Array representing the parsed values from the `scope`. */ 2339 get scopes() { 2340 var _a, _b; 2341 return (_b = (_a = this.scope) == null ? void 0 : _a.split(" ")) != null ? _b : []; 2342 } 2343 toStorageString() { 2344 new Logger("User").create("toStorageString"); 2345 return JSON.stringify({ 2346 id_token: this.id_token, 2347 session_state: this.session_state, 2348 access_token: this.access_token, 2349 refresh_token: this.refresh_token, 2350 token_type: this.token_type, 2351 scope: this.scope, 2352 profile: this.profile, 2353 expires_at: this.expires_at 2354 }); 2355 } 2356 static fromStorageString(storageString) { 2357 Logger.createStatic("User", "fromStorageString"); 2358 return new _User(JSON.parse(storageString)); 2359 } 2360}; 2361var messageSource = "oidc-client"; 2362var AbstractChildWindow = class { 2363 constructor() { 2364 this._abort = new Event("Window navigation aborted"); 2365 this._disposeHandlers = /* @__PURE__ */ new Set(); 2366 this._window = null; 2367 } 2368 async navigate(params) { 2369 const logger2 = this._logger.create("navigate"); 2370 if (!this._window) { 2371 throw new Error("Attempted to navigate on a disposed window"); 2372 } 2373 logger2.debug("setting URL in window"); 2374 this._window.location.replace(params.url); 2375 const { url, keepOpen } = await new Promise((resolve, reject) => { 2376 const listener = (e) => { 2377 var _a; 2378 const data = e.data; 2379 const origin = (_a = params.scriptOrigin) != null ? _a : window.location.origin; 2380 if (e.origin !== origin || (data == null ? void 0 : data.source) !== messageSource) { 2381 return; 2382 } 2383 try { 2384 const state = UrlUtils.readParams(data.url, params.response_mode).get("state"); 2385 if (!state) { 2386 logger2.warn("no state found in response url"); 2387 } 2388 if (e.source !== this._window && state !== params.state) { 2389 return; 2390 } 2391 } catch { 2392 this._dispose(); 2393 reject(new Error("Invalid response from window")); 2394 } 2395 resolve(data); 2396 }; 2397 window.addEventListener("message", listener, false); 2398 this._disposeHandlers.add(() => window.removeEventListener("message", listener, false)); 2399 const channel = new BroadcastChannel(`oidc-client-popup-${params.state}`); 2400 channel.addEventListener("message", listener, false); 2401 this._disposeHandlers.add(() => channel.close()); 2402 this._disposeHandlers.add(this._abort.addHandler((reason) => { 2403 this._dispose(); 2404 reject(reason); 2405 })); 2406 }); 2407 logger2.debug("got response from window"); 2408 this._dispose(); 2409 if (!keepOpen) { 2410 this.close(); 2411 } 2412 return { url }; 2413 } 2414 _dispose() { 2415 this._logger.create("_dispose"); 2416 for (const dispose of this._disposeHandlers) { 2417 dispose(); 2418 } 2419 this._disposeHandlers.clear(); 2420 } 2421 static _notifyParent(parent, url, keepOpen = false, targetOrigin = window.location.origin) { 2422 const msgData = { 2423 source: messageSource, 2424 url, 2425 keepOpen 2426 }; 2427 const logger2 = new Logger("_notifyParent"); 2428 if (parent) { 2429 logger2.debug("With parent. Using parent.postMessage."); 2430 parent.postMessage(msgData, targetOrigin); 2431 } else { 2432 logger2.debug("No parent. Using BroadcastChannel."); 2433 const state = new URL(url).searchParams.get("state"); 2434 if (!state) { 2435 throw new Error("No parent and no state in URL. Can't complete notification."); 2436 } 2437 const channel = new BroadcastChannel(`oidc-client-popup-${state}`); 2438 channel.postMessage(msgData); 2439 channel.close(); 2440 } 2441 } 2442}; 2443var DefaultPopupWindowFeatures = { 2444 location: false, 2445 toolbar: false, 2446 height: 640, 2447 closePopupWindowAfterInSeconds: -1 2448}; 2449var DefaultPopupTarget = "_blank"; 2450var DefaultAccessTokenExpiringNotificationTimeInSeconds = 60; 2451var DefaultCheckSessionIntervalInSeconds = 2; 2452var DefaultSilentRequestTimeoutInSeconds = 10; 2453var UserManagerSettingsStore = class extends OidcClientSettingsStore { 2454 constructor(args) { 2455 const { 2456 popup_redirect_uri = args.redirect_uri, 2457 popup_post_logout_redirect_uri = args.post_logout_redirect_uri, 2458 popupWindowFeatures = DefaultPopupWindowFeatures, 2459 popupWindowTarget = DefaultPopupTarget, 2460 redirectMethod = "assign", 2461 redirectTarget = "self", 2462 iframeNotifyParentOrigin = args.iframeNotifyParentOrigin, 2463 iframeScriptOrigin = args.iframeScriptOrigin, 2464 requestTimeoutInSeconds, 2465 silent_redirect_uri = args.redirect_uri, 2466 silentRequestTimeoutInSeconds, 2467 automaticSilentRenew = true, 2468 validateSubOnSilentRenew = true, 2469 includeIdTokenInSilentRenew = false, 2470 monitorSession = false, 2471 monitorAnonymousSession = false, 2472 checkSessionIntervalInSeconds = DefaultCheckSessionIntervalInSeconds, 2473 query_status_response_type = "code", 2474 stopCheckSessionOnError = true, 2475 revokeTokenTypes = ["access_token", "refresh_token"], 2476 revokeTokensOnSignout = false, 2477 includeIdTokenInSilentSignout = false, 2478 accessTokenExpiringNotificationTimeInSeconds = DefaultAccessTokenExpiringNotificationTimeInSeconds, 2479 maxSilentRenewTimeoutRetries, 2480 userStore 2481 } = args; 2482 super(args); 2483 this.popup_redirect_uri = popup_redirect_uri; 2484 this.popup_post_logout_redirect_uri = popup_post_logout_redirect_uri; 2485 this.popupWindowFeatures = popupWindowFeatures; 2486 this.popupWindowTarget = popupWindowTarget; 2487 this.redirectMethod = redirectMethod; 2488 this.redirectTarget = redirectTarget; 2489 this.iframeNotifyParentOrigin = iframeNotifyParentOrigin; 2490 this.iframeScriptOrigin = iframeScriptOrigin; 2491 this.silent_redirect_uri = silent_redirect_uri; 2492 this.silentRequestTimeoutInSeconds = silentRequestTimeoutInSeconds || requestTimeoutInSeconds || DefaultSilentRequestTimeoutInSeconds; 2493 this.automaticSilentRenew = automaticSilentRenew; 2494 this.validateSubOnSilentRenew = validateSubOnSilentRenew; 2495 this.includeIdTokenInSilentRenew = includeIdTokenInSilentRenew; 2496 this.monitorSession = monitorSession; 2497 this.monitorAnonymousSession = monitorAnonymousSession; 2498 this.checkSessionIntervalInSeconds = checkSessionIntervalInSeconds; 2499 this.stopCheckSessionOnError = stopCheckSessionOnError; 2500 this.query_status_response_type = query_status_response_type; 2501 this.revokeTokenTypes = revokeTokenTypes; 2502 this.revokeTokensOnSignout = revokeTokensOnSignout; 2503 this.includeIdTokenInSilentSignout = includeIdTokenInSilentSignout; 2504 this.accessTokenExpiringNotificationTimeInSeconds = accessTokenExpiringNotificationTimeInSeconds; 2505 this.maxSilentRenewTimeoutRetries = maxSilentRenewTimeoutRetries; 2506 if (userStore) { 2507 this.userStore = userStore; 2508 } else { 2509 const store = typeof window !== "undefined" ? window.sessionStorage : new InMemoryWebStorage(); 2510 this.userStore = new WebStorageStateStore({ store }); 2511 } 2512 } 2513}; 2514var IFrameWindow = class _IFrameWindow extends AbstractChildWindow { 2515 constructor({ 2516 silentRequestTimeoutInSeconds = DefaultSilentRequestTimeoutInSeconds 2517 }) { 2518 super(); 2519 this._logger = new Logger("IFrameWindow"); 2520 this._timeoutInSeconds = silentRequestTimeoutInSeconds; 2521 this._frame = _IFrameWindow.createHiddenIframe(); 2522 this._window = this._frame.contentWindow; 2523 } 2524 static createHiddenIframe() { 2525 const iframe = window.document.createElement("iframe"); 2526 iframe.style.visibility = "hidden"; 2527 iframe.style.position = "fixed"; 2528 iframe.style.left = "-1000px"; 2529 iframe.style.top = "0"; 2530 iframe.width = "0"; 2531 iframe.height = "0"; 2532 window.document.body.appendChild(iframe); 2533 return iframe; 2534 } 2535 async navigate(params) { 2536 this._logger.debug("navigate: Using timeout of:", this._timeoutInSeconds); 2537 const timer = setTimeout(() => void this._abort.raise(new ErrorTimeout("IFrame timed out without a response")), this._timeoutInSeconds * 1e3); 2538 this._disposeHandlers.add(() => clearTimeout(timer)); 2539 return await super.navigate(params); 2540 } 2541 close() { 2542 var _a; 2543 if (this._frame) { 2544 if (this._frame.parentNode) { 2545 this._frame.addEventListener("load", (ev) => { 2546 var _a2; 2547 const frame = ev.target; 2548 (_a2 = frame.parentNode) == null ? void 0 : _a2.removeChild(frame); 2549 void this._abort.raise(new Error("IFrame removed from DOM")); 2550 }, true); 2551 (_a = this._frame.contentWindow) == null ? void 0 : _a.location.replace("about:blank"); 2552 } 2553 this._frame = null; 2554 } 2555 this._window = null; 2556 } 2557 static notifyParent(url, targetOrigin) { 2558 return super._notifyParent(window.parent, url, false, targetOrigin); 2559 } 2560}; 2561var IFrameNavigator = class { 2562 constructor(_settings) { 2563 this._settings = _settings; 2564 this._logger = new Logger("IFrameNavigator"); 2565 } 2566 async prepare({ 2567 silentRequestTimeoutInSeconds = this._settings.silentRequestTimeoutInSeconds 2568 }) { 2569 return new IFrameWindow({ silentRequestTimeoutInSeconds }); 2570 } 2571 async callback(url) { 2572 this._logger.create("callback"); 2573 IFrameWindow.notifyParent(url, this._settings.iframeNotifyParentOrigin); 2574 } 2575}; 2576var checkForPopupClosedInterval = 500; 2577var second = 1e3; 2578var PopupWindow = class extends AbstractChildWindow { 2579 constructor({ 2580 popupWindowTarget = DefaultPopupTarget, 2581 popupWindowFeatures = {}, 2582 popupSignal, 2583 popupAbortOnClose 2584 }) { 2585 super(); 2586 this._logger = new Logger("PopupWindow"); 2587 const centeredPopup = PopupUtils.center({ ...DefaultPopupWindowFeatures, ...popupWindowFeatures }); 2588 this._window = window.open(void 0, popupWindowTarget, PopupUtils.serialize(centeredPopup)); 2589 this.abortOnClose = Boolean(popupAbortOnClose); 2590 if (popupSignal) { 2591 popupSignal.addEventListener("abort", () => { 2592 var _a; 2593 void this._abort.raise(new Error((_a = popupSignal.reason) != null ? _a : "Popup aborted")); 2594 }); 2595 } 2596 if (popupWindowFeatures.closePopupWindowAfterInSeconds && popupWindowFeatures.closePopupWindowAfterInSeconds > 0) { 2597 setTimeout(() => { 2598 if (!this._window || typeof this._window.closed !== "boolean" || this._window.closed) { 2599 void this._abort.raise(new Error("Popup blocked by user")); 2600 return; 2601 } 2602 this.close(); 2603 }, popupWindowFeatures.closePopupWindowAfterInSeconds * second); 2604 } 2605 } 2606 async navigate(params) { 2607 var _a; 2608 (_a = this._window) == null ? void 0 : _a.focus(); 2609 const popupClosedInterval = setInterval(() => { 2610 if (!this._window || this._window.closed) { 2611 this._logger.debug("Popup closed by user or isolated by redirect"); 2612 clearPopupClosedInterval(); 2613 this._disposeHandlers.delete(clearPopupClosedInterval); 2614 if (this.abortOnClose) { 2615 void this._abort.raise(new Error("Popup closed by user")); 2616 } 2617 } 2618 }, checkForPopupClosedInterval); 2619 const clearPopupClosedInterval = () => clearInterval(popupClosedInterval); 2620 this._disposeHandlers.add(clearPopupClosedInterval); 2621 return await super.navigate(params); 2622 } 2623 close() { 2624 if (this._window) { 2625 if (!this._window.closed) { 2626 this._window.close(); 2627 void this._abort.raise(new Error("Popup closed")); 2628 } 2629 } 2630 this._window = null; 2631 } 2632 static notifyOpener(url, keepOpen) { 2633 super._notifyParent(window.opener, url, keepOpen); 2634 if (!keepOpen && !window.opener) { 2635 window.close(); 2636 } 2637 } 2638}; 2639var PopupNavigator = class { 2640 constructor(_settings) { 2641 this._settings = _settings; 2642 this._logger = new Logger("PopupNavigator"); 2643 } 2644 async prepare({ 2645 popupWindowFeatures = this._settings.popupWindowFeatures, 2646 popupWindowTarget = this._settings.popupWindowTarget, 2647 popupSignal, 2648 popupAbortOnClose 2649 }) { 2650 return new PopupWindow({ 2651 popupWindowFeatures, 2652 popupWindowTarget, 2653 popupSignal, 2654 popupAbortOnClose 2655 }); 2656 } 2657 async callback(url, { keepOpen = false }) { 2658 this._logger.create("callback"); 2659 PopupWindow.notifyOpener(url, keepOpen); 2660 } 2661}; 2662var RedirectNavigator = class { 2663 constructor(_settings) { 2664 this._settings = _settings; 2665 this._logger = new Logger("RedirectNavigator"); 2666 } 2667 async prepare({ 2668 redirectMethod = this._settings.redirectMethod, 2669 redirectTarget = this._settings.redirectTarget 2670 }) { 2671 var _a; 2672 this._logger.create("prepare"); 2673 let targetWindow = window.self; 2674 if (redirectTarget === "top") { 2675 targetWindow = (_a = window.top) != null ? _a : window.self; 2676 } 2677 const redirect = targetWindow.location[redirectMethod].bind(targetWindow.location); 2678 let abort; 2679 return { 2680 navigate: async (params) => { 2681 this._logger.create("navigate"); 2682 const promise = new Promise((resolve, reject) => { 2683 abort = reject; 2684 window.addEventListener("pageshow", () => resolve(window.location.href)); 2685 redirect(params.url); 2686 }); 2687 return await promise; 2688 }, 2689 close: () => { 2690 this._logger.create("close"); 2691 abort == null ? void 0 : abort(new Error("Redirect aborted")); 2692 targetWindow.stop(); 2693 } 2694 }; 2695 } 2696 async callback() { 2697 return; 2698 } 2699}; 2700var UserManagerEvents = class extends AccessTokenEvents { 2701 constructor(settings) { 2702 super({ expiringNotificationTimeInSeconds: settings.accessTokenExpiringNotificationTimeInSeconds }); 2703 this._logger = new Logger("UserManagerEvents"); 2704 this._userLoaded = new Event("User loaded"); 2705 this._userUnloaded = new Event("User unloaded"); 2706 this._silentRenewError = new Event("Silent renew error"); 2707 this._userSignedIn = new Event("User signed in"); 2708 this._userSignedOut = new Event("User signed out"); 2709 this._userSessionChanged = new Event("User session changed"); 2710 } 2711 async load(user, raiseEvent = true) { 2712 await super.load(user); 2713 if (raiseEvent) { 2714 await this._userLoaded.raise(user); 2715 } 2716 } 2717 async unload() { 2718 await super.unload(); 2719 await this._userUnloaded.raise(); 2720 } 2721 /** 2722 * Add callback: Raised when a user session has been established (or re-established). 2723 */ 2724 addUserLoaded(cb) { 2725 return this._userLoaded.addHandler(cb); 2726 } 2727 /** 2728 * Remove callback: Raised when a user session has been established (or re-established). 2729 */ 2730 removeUserLoaded(cb) { 2731 return this._userLoaded.removeHandler(cb); 2732 } 2733 /** 2734 * Add callback: Raised when a user session has been terminated. 2735 */ 2736 addUserUnloaded(cb) { 2737 return this._userUnloaded.addHandler(cb); 2738 } 2739 /** 2740 * Remove callback: Raised when a user session has been terminated. 2741 */ 2742 removeUserUnloaded(cb) { 2743 return this._userUnloaded.removeHandler(cb); 2744 } 2745 /** 2746 * Add callback: Raised when the automatic silent renew has failed. 2747 */ 2748 addSilentRenewError(cb) { 2749 return this._silentRenewError.addHandler(cb); 2750 } 2751 /** 2752 * Remove callback: Raised when the automatic silent renew has failed. 2753 */ 2754 removeSilentRenewError(cb) { 2755 return this._silentRenewError.removeHandler(cb); 2756 } 2757 /** 2758 * @internal 2759 */ 2760 async _raiseSilentRenewError(e) { 2761 await this._silentRenewError.raise(e); 2762 } 2763 /** 2764 * Add callback: Raised when the user is signed in (when `monitorSession` is set). 2765 * @see {@link UserManagerSettings.monitorSession} 2766 */ 2767 addUserSignedIn(cb) { 2768 return this._userSignedIn.addHandler(cb); 2769 } 2770 /** 2771 * Remove callback: Raised when the user is signed in (when `monitorSession` is set). 2772 */ 2773 removeUserSignedIn(cb) { 2774 this._userSignedIn.removeHandler(cb); 2775 } 2776 /** 2777 * @internal 2778 */ 2779 async _raiseUserSignedIn() { 2780 await this._userSignedIn.raise(); 2781 } 2782 /** 2783 * Add callback: Raised when the user's sign-in status at the OP has changed (when `monitorSession` is set). 2784 * @see {@link UserManagerSettings.monitorSession} 2785 */ 2786 addUserSignedOut(cb) { 2787 return this._userSignedOut.addHandler(cb); 2788 } 2789 /** 2790 * Remove callback: Raised when the user's sign-in status at the OP has changed (when `monitorSession` is set). 2791 */ 2792 removeUserSignedOut(cb) { 2793 this._userSignedOut.removeHandler(cb); 2794 } 2795 /** 2796 * @internal 2797 */ 2798 async _raiseUserSignedOut() { 2799 await this._userSignedOut.raise(); 2800 } 2801 /** 2802 * Add callback: Raised when the user session changed (when `monitorSession` is set). 2803 * @see {@link UserManagerSettings.monitorSession} 2804 */ 2805 addUserSessionChanged(cb) { 2806 return this._userSessionChanged.addHandler(cb); 2807 } 2808 /** 2809 * Remove callback: Raised when the user session changed (when `monitorSession` is set). 2810 */ 2811 removeUserSessionChanged(cb) { 2812 this._userSessionChanged.removeHandler(cb); 2813 } 2814 /** 2815 * @internal 2816 */ 2817 async _raiseUserSessionChanged() { 2818 await this._userSessionChanged.raise(); 2819 } 2820}; 2821var SilentRenewService = class { 2822 constructor(_userManager) { 2823 this._userManager = _userManager; 2824 this._logger = new Logger("SilentRenewService"); 2825 this._isStarted = false; 2826 this._retryTimer = new Timer("Retry Silent Renew"); 2827 this._timeoutRetryCount = 0; 2828 this._tokenExpiring = async () => { 2829 const logger2 = this._logger.create("_tokenExpiring"); 2830 try { 2831 await this._userManager.signinSilent(); 2832 this._timeoutRetryCount = 0; 2833 logger2.debug("silent token renewal successful"); 2834 } catch (err) { 2835 if (err instanceof ErrorTimeout) { 2836 this._timeoutRetryCount++; 2837 const maxRetries = this._userManager.settings.maxSilentRenewTimeoutRetries; 2838 const hasReachedLimit = maxRetries !== void 0 && this._timeoutRetryCount > maxRetries; 2839 if (hasReachedLimit) { 2840 logger2.error( 2841 `Timeout retry limit reached (${this._timeoutRetryCount} > ${maxRetries}), raising silentRenewError:`, 2842 err 2843 ); 2844 this._timeoutRetryCount = 0; 2845 await this._userManager.events._raiseSilentRenewError(err); 2846 return; 2847 } 2848 logger2.warn( 2849 `ErrorTimeout from signinSilent (attempt ${this._timeoutRetryCount}), retry in 5s:`, 2850 err 2851 ); 2852 this._retryTimer.init(5); 2853 return; 2854 } 2855 logger2.error("Error from signinSilent:", err); 2856 this._timeoutRetryCount = 0; 2857 await this._userManager.events._raiseSilentRenewError(err); 2858 } 2859 }; 2860 } 2861 async start() { 2862 const logger2 = this._logger.create("start"); 2863 if (!this._isStarted) { 2864 this._isStarted = true; 2865 this._userManager.events.addAccessTokenExpiring(this._tokenExpiring); 2866 this._retryTimer.addHandler(this._tokenExpiring); 2867 try { 2868 await this._userManager.getUser(); 2869 } catch (err) { 2870 logger2.error("getUser error", err); 2871 } 2872 } 2873 } 2874 stop() { 2875 if (this._isStarted) { 2876 this._retryTimer.cancel(); 2877 this._retryTimer.removeHandler(this._tokenExpiring); 2878 this._userManager.events.removeAccessTokenExpiring(this._tokenExpiring); 2879 this._isStarted = false; 2880 } 2881 } 2882}; 2883var RefreshState = class { 2884 constructor(args) { 2885 this.refresh_token = args.refresh_token; 2886 this.id_token = args.id_token; 2887 this.session_state = args.session_state; 2888 this.scope = args.scope; 2889 this.profile = args.profile; 2890 this.data = args.state; 2891 } 2892}; 2893var UserManager = class { 2894 constructor(settings, redirectNavigator, popupNavigator, iframeNavigator) { 2895 this._logger = new Logger("UserManager"); 2896 this.settings = new UserManagerSettingsStore(settings); 2897 this._client = new OidcClient(settings); 2898 this._redirectNavigator = redirectNavigator != null ? redirectNavigator : new RedirectNavigator(this.settings); 2899 this._popupNavigator = popupNavigator != null ? popupNavigator : new PopupNavigator(this.settings); 2900 this._iframeNavigator = iframeNavigator != null ? iframeNavigator : new IFrameNavigator(this.settings); 2901 this._events = new UserManagerEvents(this.settings); 2902 this._silentRenewService = new SilentRenewService(this); 2903 if (this.settings.automaticSilentRenew) { 2904 this.startSilentRenew(); 2905 } 2906 this._sessionMonitor = null; 2907 if (this.settings.monitorSession) { 2908 this._sessionMonitor = new SessionMonitor(this); 2909 } 2910 } 2911 /** 2912 * Get object used to register for events raised by the `UserManager`. 2913 */ 2914 get events() { 2915 return this._events; 2916 } 2917 /** 2918 * Get object used to access the metadata configuration of the identity provider. 2919 */ 2920 get metadataService() { 2921 return this._client.metadataService; 2922 } 2923 /** 2924 * Load the `User` object for the currently authenticated user. 2925 * 2926 * @param raiseEvent - If `true`, the `UserLoaded` event will be raised. Defaults to false. 2927 * @returns A promise 2928 */ 2929 async getUser(raiseEvent = false) { 2930 const logger2 = this._logger.create("getUser"); 2931 const user = await this._loadUser(); 2932 if (user) { 2933 logger2.info("user loaded"); 2934 await this._events.load(user, raiseEvent); 2935 return user; 2936 } 2937 logger2.info("user not found in storage"); 2938 return null; 2939 } 2940 /** 2941 * Remove from any storage the currently authenticated user. 2942 * 2943 * @returns A promise 2944 */ 2945 async removeUser() { 2946 const logger2 = this._logger.create("removeUser"); 2947 await this.storeUser(null); 2948 logger2.info("user removed from storage"); 2949 await this._events.unload(); 2950 } 2951 /** 2952 * Trigger a redirect of the current window to the authorization endpoint. 2953 * 2954 * @returns A promise 2955 * 2956 * @throws `Error` In cases of wrong authentication. 2957 */ 2958 async signinRedirect(args = {}) { 2959 var _a; 2960 this._logger.create("signinRedirect"); 2961 const { 2962 redirectMethod, 2963 ...requestArgs 2964 } = args; 2965 let dpopJkt; 2966 if ((_a = this.settings.dpop) == null ? void 0 : _a.bind_authorization_code) { 2967 dpopJkt = await this.generateDPoPJkt(this.settings.dpop); 2968 } 2969 const handle = await this._redirectNavigator.prepare({ redirectMethod }); 2970 await this._signinStart({ 2971 request_type: "si:r", 2972 dpopJkt, 2973 ...requestArgs 2974 }, handle); 2975 } 2976 /** 2977 * Process the response (callback) from the authorization endpoint. 2978 * It is recommended to use {@link UserManager.signinCallback} instead. 2979 * 2980 * @returns A promise containing the authenticated `User`. 2981 * 2982 * @see {@link UserManager.signinCallback} 2983 */ 2984 async signinRedirectCallback(url = window.location.href) { 2985 const logger2 = this._logger.create("signinRedirectCallback"); 2986 const user = await this._signinEnd(url); 2987 if (user.profile && user.profile.sub) { 2988 logger2.info("success, signed in subject", user.profile.sub); 2989 } else { 2990 logger2.info("no subject"); 2991 } 2992 return user; 2993 } 2994 /** 2995 * Trigger the signin with user/password. 2996 * 2997 * @returns A promise containing the authenticated `User`. 2998 * @throws {@link ErrorResponse} In cases of wrong authentication. 2999 */ 3000 async signinResourceOwnerCredentials({ 3001 username, 3002 password, 3003 skipUserInfo = false 3004 }) { 3005 const logger2 = this._logger.create("signinResourceOwnerCredential"); 3006 const signinResponse = await this._client.processResourceOwnerPasswordCredentials({ 3007 username, 3008 password, 3009 skipUserInfo, 3010 extraTokenParams: this.settings.extraTokenParams 3011 }); 3012 logger2.debug("got signin response"); 3013 const user = await this._buildUser(signinResponse); 3014 if (user.profile && user.profile.sub) { 3015 logger2.info("success, signed in subject", user.profile.sub); 3016 } else { 3017 logger2.info("no subject"); 3018 } 3019 return user; 3020 } 3021 /** 3022 * Trigger a request (via a popup window) to the authorization endpoint. 3023 * 3024 * @returns A promise containing the authenticated `User`. 3025 * @throws `Error` In cases of wrong authentication. 3026 */ 3027 async signinPopup(args = {}) { 3028 var _a; 3029 const logger2 = this._logger.create("signinPopup"); 3030 let dpopJkt; 3031 if ((_a = this.settings.dpop) == null ? void 0 : _a.bind_authorization_code) { 3032 dpopJkt = await this.generateDPoPJkt(this.settings.dpop); 3033 } 3034 const { 3035 popupWindowFeatures, 3036 popupWindowTarget, 3037 popupSignal, 3038 popupAbortOnClose, 3039 ...requestArgs 3040 } = args; 3041 const url = this.settings.popup_redirect_uri; 3042 if (!url) { 3043 logger2.throw(new Error("No popup_redirect_uri configured")); 3044 } 3045 const handle = await this._popupNavigator.prepare({ popupWindowFeatures, popupWindowTarget, popupSignal, popupAbortOnClose }); 3046 const user = await this._signin({ 3047 request_type: "si:p", 3048 redirect_uri: url, 3049 display: "popup", 3050 dpopJkt, 3051 ...requestArgs 3052 }, handle); 3053 if (user) { 3054 if (user.profile && user.profile.sub) { 3055 logger2.info("success, signed in subject", user.profile.sub); 3056 } else { 3057 logger2.info("no subject"); 3058 } 3059 } 3060 return user; 3061 } 3062 /** 3063 * Notify the opening window of response (callback) from the authorization endpoint. 3064 * It is recommended to use {@link UserManager.signinCallback} instead. 3065 * 3066 * @returns A promise 3067 * 3068 * @see {@link UserManager.signinCallback} 3069 */ 3070 async signinPopupCallback(url = window.location.href, keepOpen = false) { 3071 const logger2 = this._logger.create("signinPopupCallback"); 3072 await this._popupNavigator.callback(url, { keepOpen }); 3073 logger2.info("success"); 3074 } 3075 /** 3076 * Trigger a silent request (via refresh token or an iframe) to the authorization endpoint. 3077 * 3078 * @returns A promise that contains the authenticated `User`. 3079 */ 3080 async signinSilent(args = {}) { 3081 var _a, _b; 3082 const logger2 = this._logger.create("signinSilent"); 3083 const { 3084 silentRequestTimeoutInSeconds, 3085 ...requestArgs 3086 } = args; 3087 let user = await this._loadUser(); 3088 if (!args.forceIframeAuth && (user == null ? void 0 : user.refresh_token)) { 3089 logger2.debug("using refresh token"); 3090 const state = new RefreshState(user); 3091 return await this._useRefreshToken({ 3092 state, 3093 redirect_uri: requestArgs.redirect_uri, 3094 resource: requestArgs.resource, 3095 extraTokenParams: requestArgs.extraTokenParams, 3096 timeoutInSeconds: silentRequestTimeoutInSeconds 3097 }); 3098 } 3099 let dpopJkt; 3100 if ((_a = this.settings.dpop) == null ? void 0 : _a.bind_authorization_code) { 3101 dpopJkt = await this.generateDPoPJkt(this.settings.dpop); 3102 } 3103 const url = this.settings.silent_redirect_uri; 3104 if (!url) { 3105 logger2.throw(new Error("No silent_redirect_uri configured")); 3106 } 3107 let verifySub; 3108 if (user && this.settings.validateSubOnSilentRenew) { 3109 logger2.debug("subject prior to silent renew:", user.profile.sub); 3110 verifySub = user.profile.sub; 3111 } 3112 const handle = await this._iframeNavigator.prepare({ silentRequestTimeoutInSeconds }); 3113 user = await this._signin({ 3114 request_type: "si:s", 3115 redirect_uri: url, 3116 prompt: "none", 3117 id_token_hint: this.settings.includeIdTokenInSilentRenew ? user == null ? void 0 : user.id_token : void 0, 3118 dpopJkt, 3119 ...requestArgs 3120 }, handle, verifySub); 3121 if (user) { 3122 if ((_b = user.profile) == null ? void 0 : _b.sub) { 3123 logger2.info("success, signed in subject", user.profile.sub); 3124 } else { 3125 logger2.info("no subject"); 3126 } 3127 } 3128 return user; 3129 } 3130 async _useRefreshToken(args) { 3131 const response = await this._client.useRefreshToken({ 3132 timeoutInSeconds: this.settings.silentRequestTimeoutInSeconds, 3133 ...args 3134 }); 3135 const user = new User({ ...args.state, ...response }); 3136 await this.storeUser(user); 3137 await this._events.load(user); 3138 return user; 3139 } 3140 /** 3141 * 3142 * Notify the parent window of response (callback) from the authorization endpoint. 3143 * It is recommended to use {@link UserManager.signinCallback} instead. 3144 * 3145 * @returns A promise 3146 * 3147 * @see {@link UserManager.signinCallback} 3148 */ 3149 async signinSilentCallback(url = window.location.href) { 3150 const logger2 = this._logger.create("signinSilentCallback"); 3151 await this._iframeNavigator.callback(url); 3152 logger2.info("success"); 3153 } 3154 /** 3155 * Process any response (callback) from the authorization endpoint, by dispatching the request_type 3156 * and executing one of the following functions: 3157 * - {@link UserManager.signinRedirectCallback} 3158 * - {@link UserManager.signinPopupCallback} 3159 * - {@link UserManager.signinSilentCallback} 3160 * 3161 * @throws `Error` If request_type is unknown or signin cannot be processed. 3162 */ 3163 async signinCallback(url = window.location.href) { 3164 const { state } = await this._client.readSigninResponseState(url); 3165 switch (state.request_type) { 3166 case "si:r": 3167 return await this.signinRedirectCallback(url); 3168 case "si:p": 3169 await this.signinPopupCallback(url); 3170 break; 3171 case "si:s": 3172 await this.signinSilentCallback(url); 3173 break; 3174 default: 3175 throw new Error("invalid request_type in state"); 3176 } 3177 return void 0; 3178 } 3179 /** 3180 * Process any response (callback) from the end session endpoint, by dispatching the request_type 3181 * and executing one of the following functions: 3182 * - {@link UserManager.signoutRedirectCallback} 3183 * - {@link UserManager.signoutPopupCallback} 3184 * - {@link UserManager.signoutSilentCallback} 3185 * 3186 * @throws `Error` If request_type is unknown or signout cannot be processed. 3187 */ 3188 async signoutCallback(url = window.location.href, keepOpen = false) { 3189 const { state } = await this._client.readSignoutResponseState(url); 3190 if (!state) { 3191 return void 0; 3192 } 3193 switch (state.request_type) { 3194 case "so:r": 3195 return await this.signoutRedirectCallback(url); 3196 case "so:p": 3197 await this.signoutPopupCallback(url, keepOpen); 3198 break; 3199 case "so:s": 3200 await this.signoutSilentCallback(url); 3201 break; 3202 default: 3203 throw new Error("invalid request_type in state"); 3204 } 3205 return void 0; 3206 } 3207 /** 3208 * Query OP for user's current signin status. 3209 * 3210 * @returns A promise object with session_state and subject identifier. 3211 */ 3212 async querySessionStatus(args = {}) { 3213 const logger2 = this._logger.create("querySessionStatus"); 3214 const { 3215 silentRequestTimeoutInSeconds, 3216 ...requestArgs 3217 } = args; 3218 const url = this.settings.silent_redirect_uri; 3219 if (!url) { 3220 logger2.throw(new Error("No silent_redirect_uri configured")); 3221 } 3222 const user = await this._loadUser(); 3223 const handle = await this._iframeNavigator.prepare({ silentRequestTimeoutInSeconds }); 3224 const navResponse = await this._signinStart({ 3225 request_type: "si:s", 3226 // this acts like a signin silent 3227 redirect_uri: url, 3228 prompt: "none", 3229 id_token_hint: this.settings.includeIdTokenInSilentRenew ? user == null ? void 0 : user.id_token : void 0, 3230 response_type: this.settings.query_status_response_type, 3231 scope: "openid", 3232 skipUserInfo: true, 3233 ...requestArgs 3234 }, handle); 3235 try { 3236 const extraHeaders = {}; 3237 const signinResponse = await this._client.processSigninResponse(navResponse.url, extraHeaders); 3238 logger2.debug("got signin response"); 3239 if (signinResponse.session_state && signinResponse.profile.sub) { 3240 logger2.info("success for subject", signinResponse.profile.sub); 3241 return { 3242 session_state: signinResponse.session_state, 3243 sub: signinResponse.profile.sub 3244 }; 3245 } 3246 logger2.info("success, user not authenticated"); 3247 return null; 3248 } catch (err) { 3249 if (this.settings.monitorAnonymousSession && err instanceof ErrorResponse) { 3250 switch (err.error) { 3251 case "login_required": 3252 case "consent_required": 3253 case "interaction_required": 3254 case "account_selection_required": 3255 logger2.info("success for anonymous user"); 3256 return { 3257 session_state: err.session_state 3258 }; 3259 } 3260 } 3261 throw err; 3262 } 3263 } 3264 async _signin(args, handle, verifySub) { 3265 const navResponse = await this._signinStart(args, handle); 3266 return await this._signinEnd(navResponse.url, verifySub); 3267 } 3268 async _signinStart(args, handle) { 3269 const logger2 = this._logger.create("_signinStart"); 3270 try { 3271 const signinRequest = await this._client.createSigninRequest(args); 3272 logger2.debug("got signin request"); 3273 return await handle.navigate({ 3274 url: signinRequest.url, 3275 state: signinRequest.state.id, 3276 response_mode: signinRequest.state.response_mode, 3277 scriptOrigin: this.settings.iframeScriptOrigin 3278 }); 3279 } catch (err) { 3280 logger2.debug("error after preparing navigator, closing navigator window"); 3281 handle.close(); 3282 throw err; 3283 } 3284 } 3285 async _signinEnd(url, verifySub) { 3286 const logger2 = this._logger.create("_signinEnd"); 3287 const extraHeaders = {}; 3288 const signinResponse = await this._client.processSigninResponse(url, extraHeaders); 3289 logger2.debug("got signin response"); 3290 const user = await this._buildUser(signinResponse, verifySub); 3291 return user; 3292 } 3293 async _buildUser(signinResponse, verifySub) { 3294 const logger2 = this._logger.create("_buildUser"); 3295 const user = new User(signinResponse); 3296 if (verifySub) { 3297 if (verifySub !== user.profile.sub) { 3298 logger2.debug("current user does not match user returned from signin. sub from signin:", user.profile.sub); 3299 throw new ErrorResponse({ ...signinResponse, error: "login_required" }); 3300 } 3301 logger2.debug("current user matches user returned from signin"); 3302 } 3303 await this.storeUser(user); 3304 logger2.debug("user stored"); 3305 await this._events.load(user); 3306 return user; 3307 } 3308 /** 3309 * Trigger a redirect of the current window to the end session endpoint. 3310 * 3311 * @returns A promise 3312 */ 3313 async signoutRedirect(args = {}) { 3314 const logger2 = this._logger.create("signoutRedirect"); 3315 const { 3316 redirectMethod, 3317 ...requestArgs 3318 } = args; 3319 const handle = await this._redirectNavigator.prepare({ redirectMethod }); 3320 await this._signoutStart({ 3321 request_type: "so:r", 3322 post_logout_redirect_uri: this.settings.post_logout_redirect_uri, 3323 ...requestArgs 3324 }, handle); 3325 logger2.info("success"); 3326 } 3327 /** 3328 * Process response (callback) from the end session endpoint. 3329 * It is recommended to use {@link UserManager.signoutCallback} instead. 3330 * 3331 * @returns A promise containing signout response 3332 * 3333 * @see {@link UserManager.signoutCallback} 3334 */ 3335 async signoutRedirectCallback(url = window.location.href) { 3336 const logger2 = this._logger.create("signoutRedirectCallback"); 3337 const response = await this._signoutEnd(url); 3338 logger2.info("success"); 3339 return response; 3340 } 3341 /** 3342 * Trigger a redirect of a popup window to the end session endpoint. 3343 * 3344 * @returns A promise 3345 */ 3346 async signoutPopup(args = {}) { 3347 const logger2 = this._logger.create("signoutPopup"); 3348 const { 3349 popupWindowFeatures, 3350 popupWindowTarget, 3351 popupSignal, 3352 ...requestArgs 3353 } = args; 3354 const url = this.settings.popup_post_logout_redirect_uri; 3355 const handle = await this._popupNavigator.prepare({ popupWindowFeatures, popupWindowTarget, popupSignal }); 3356 await this._signout({ 3357 request_type: "so:p", 3358 post_logout_redirect_uri: url, 3359 // we're putting a dummy entry in here because we 3360 // need a unique id from the state for notification 3361 // to the parent window, which is necessary if we 3362 // plan to return back to the client after signout 3363 // and so we can close the popup after signout 3364 state: url == null ? void 0 : {}, 3365 ...requestArgs 3366 }, handle); 3367 logger2.info("success"); 3368 } 3369 /** 3370 * Process response (callback) from the end session endpoint from a popup window. 3371 * It is recommended to use {@link UserManager.signoutCallback} instead. 3372 * 3373 * @returns A promise 3374 * 3375 * @see {@link UserManager.signoutCallback} 3376 */ 3377 async signoutPopupCallback(url = window.location.href, keepOpen = false) { 3378 const logger2 = this._logger.create("signoutPopupCallback"); 3379 await this._popupNavigator.callback(url, { keepOpen }); 3380 logger2.info("success"); 3381 } 3382 async _signout(args, handle) { 3383 const navResponse = await this._signoutStart(args, handle); 3384 return await this._signoutEnd(navResponse.url); 3385 } 3386 async _signoutStart(args = {}, handle) { 3387 var _a; 3388 const logger2 = this._logger.create("_signoutStart"); 3389 try { 3390 const user = await this._loadUser(); 3391 logger2.debug("loaded current user from storage"); 3392 if (this.settings.revokeTokensOnSignout) { 3393 await this._revokeInternal(user); 3394 } 3395 const id_token = args.id_token_hint || user && user.id_token; 3396 if (id_token) { 3397 logger2.debug("setting id_token_hint in signout request"); 3398 args.id_token_hint = id_token; 3399 } 3400 await this.removeUser(); 3401 logger2.debug("user removed, creating signout request"); 3402 const signoutRequest = await this._client.createSignoutRequest(args); 3403 logger2.debug("got signout request"); 3404 return await handle.navigate({ 3405 url: signoutRequest.url, 3406 state: (_a = signoutRequest.state) == null ? void 0 : _a.id, 3407 scriptOrigin: this.settings.iframeScriptOrigin 3408 }); 3409 } catch (err) { 3410 logger2.debug("error after preparing navigator, closing navigator window"); 3411 handle.close(); 3412 throw err; 3413 } 3414 } 3415 async _signoutEnd(url) { 3416 const logger2 = this._logger.create("_signoutEnd"); 3417 const signoutResponse = await this._client.processSignoutResponse(url); 3418 logger2.debug("got signout response"); 3419 return signoutResponse; 3420 } 3421 /** 3422 * Trigger a silent request (via an iframe) to the end session endpoint. 3423 * 3424 * @returns A promise 3425 */ 3426 async signoutSilent(args = {}) { 3427 var _a; 3428 const logger2 = this._logger.create("signoutSilent"); 3429 const { 3430 silentRequestTimeoutInSeconds, 3431 ...requestArgs 3432 } = args; 3433 const id_token_hint = this.settings.includeIdTokenInSilentSignout ? (_a = await this._loadUser()) == null ? void 0 : _a.id_token : void 0; 3434 const url = this.settings.popup_post_logout_redirect_uri; 3435 const handle = await this._iframeNavigator.prepare({ silentRequestTimeoutInSeconds }); 3436 await this._signout({ 3437 request_type: "so:s", 3438 post_logout_redirect_uri: url, 3439 id_token_hint, 3440 ...requestArgs 3441 }, handle); 3442 logger2.info("success"); 3443 } 3444 /** 3445 * Notify the parent window of response (callback) from the end session endpoint. 3446 * It is recommended to use {@link UserManager.signoutCallback} instead. 3447 * 3448 * @returns A promise 3449 * 3450 * @see {@link UserManager.signoutCallback} 3451 */ 3452 async signoutSilentCallback(url = window.location.href) { 3453 const logger2 = this._logger.create("signoutSilentCallback"); 3454 await this._iframeNavigator.callback(url); 3455 logger2.info("success"); 3456 } 3457 async revokeTokens(types) { 3458 const user = await this._loadUser(); 3459 await this._revokeInternal(user, types); 3460 } 3461 async _revokeInternal(user, types = this.settings.revokeTokenTypes) { 3462 const logger2 = this._logger.create("_revokeInternal"); 3463 if (!user) return; 3464 const typesPresent = types.filter((type) => typeof user[type] === "string"); 3465 if (!typesPresent.length) { 3466 logger2.debug("no need to revoke due to no token(s)"); 3467 return; 3468 } 3469 for (const type of typesPresent) { 3470 await this._client.revokeToken( 3471 user[type], 3472 type 3473 ); 3474 logger2.info(`${type} revoked successfully`); 3475 if (type !== "access_token") { 3476 user[type] = null; 3477 } 3478 } 3479 await this.storeUser(user); 3480 logger2.debug("user stored"); 3481 await this._events.load(user); 3482 } 3483 /** 3484 * Enables silent renew for the `UserManager`. 3485 */ 3486 startSilentRenew() { 3487 this._logger.create("startSilentRenew"); 3488 void this._silentRenewService.start(); 3489 } 3490 /** 3491 * Disables silent renew for the `UserManager`. 3492 */ 3493 stopSilentRenew() { 3494 this._silentRenewService.stop(); 3495 } 3496 get _userStoreKey() { 3497 return `user:${this.settings.authority}:${this.settings.client_id}`; 3498 } 3499 async _loadUser() { 3500 const logger2 = this._logger.create("_loadUser"); 3501 const storageString = await this.settings.userStore.get(this._userStoreKey); 3502 if (storageString) { 3503 logger2.debug("user storageString loaded"); 3504 return User.fromStorageString(storageString); 3505 } 3506 logger2.debug("no user storageString"); 3507 return null; 3508 } 3509 async storeUser(user) { 3510 const logger2 = this._logger.create("storeUser"); 3511 if (user) { 3512 logger2.debug("storing user"); 3513 const storageString = user.toStorageString(); 3514 await this.settings.userStore.set(this._userStoreKey, storageString); 3515 } else { 3516 this._logger.debug("removing user"); 3517 await this.settings.userStore.remove(this._userStoreKey); 3518 if (this.settings.dpop) { 3519 await this.settings.dpop.store.remove(this.settings.client_id); 3520 } 3521 } 3522 } 3523 /** 3524 * Removes stale state entries in storage for incomplete authorize requests. 3525 */ 3526 async clearStaleState() { 3527 await this._client.clearStaleState(); 3528 } 3529 /** 3530 * Dynamically generates a DPoP proof for a given user, URL and optional Http method. 3531 * This method is useful when you need to make a request to a resource server 3532 * with fetch or similar, and you need to include a DPoP proof in a DPoP header. 3533 * @param url - The URL to generate the DPoP proof for 3534 * @param user - The user to generate the DPoP proof for 3535 * @param httpMethod - Optional, defaults to "GET" 3536 * @param nonce - Optional nonce provided by the resource server 3537 * 3538 * @returns A promise containing the DPoP proof or undefined if DPoP is not enabled/no user is found. 3539 */ 3540 async dpopProof(url, user, httpMethod, nonce) { 3541 var _a, _b; 3542 const dpopState = await ((_b = (_a = this.settings.dpop) == null ? void 0 : _a.store) == null ? void 0 : _b.get(this.settings.client_id)); 3543 if (dpopState) { 3544 return await CryptoUtils.generateDPoPProof({ 3545 url, 3546 accessToken: user == null ? void 0 : user.access_token, 3547 httpMethod, 3548 keyPair: dpopState.keys, 3549 nonce 3550 }); 3551 } 3552 return void 0; 3553 } 3554 async generateDPoPJkt(dpopSettings) { 3555 let dpopState = await dpopSettings.store.get(this.settings.client_id); 3556 if (!dpopState) { 3557 const dpopKeys = await CryptoUtils.generateDPoPKeys(); 3558 dpopState = new DPoPState(dpopKeys); 3559 await dpopSettings.store.set(this.settings.client_id, dpopState); 3560 } 3561 return await CryptoUtils.generateDPoPJkt(dpopState.keys); 3562 } 3563}; 3564
vendor: 10,951 bytes, lines 3565-3898
3565// node_modules/react-oidc-context/dist/esm/react-oidc-context.js 3566var import_react2 = __toESM(require_react()); 3567var import_react3 = __toESM(require_react()); 3568var import_react4 = __toESM(require_react()); 3569var import_react5 = __toESM(require_react()); 3570var import_react6 = __toESM(require_react()); 3571var AuthContext = import_react.default.createContext(void 0); 3572AuthContext.displayName = "AuthContext"; 3573var initialAuthState = { 3574 isLoading: true, 3575 isAuthenticated: false 3576}; 3577var reducer = (state, action) => { 3578 switch (action.type) { 3579 case "INITIALISED": 3580 case "USER_LOADED": 3581 return { 3582 ...state, 3583 user: action.user, 3584 isLoading: false, 3585 isAuthenticated: action.user ? !action.user.expired : false, 3586 error: void 0 3587 }; 3588 case "USER_SIGNED_OUT": 3589 case "USER_UNLOADED": 3590 return { 3591 ...state, 3592 user: void 0, 3593 isAuthenticated: false 3594 }; 3595 case "NAVIGATOR_INIT": 3596 return { 3597 ...state, 3598 isLoading: true, 3599 activeNavigator: action.method 3600 }; 3601 case "NAVIGATOR_CLOSE": 3602 return { 3603 ...state, 3604 isLoading: false, 3605 activeNavigator: void 0 3606 }; 3607 case "ERROR": { 3608 const error = action.error; 3609 error["toString"] = () => `${error.name}: ${error.message}`; 3610 return { 3611 ...state, 3612 isLoading: false, 3613 error 3614 }; 3615 } 3616 default: { 3617 const innerError = new TypeError(`unknown type ${action["type"]}`); 3618 const error = { 3619 name: innerError.name, 3620 message: innerError.message, 3621 innerError, 3622 stack: innerError.stack, 3623 source: "unknown" 3624 }; 3625 error["toString"] = () => `${error.name}: ${error.message}`; 3626 return { 3627 ...state, 3628 isLoading: false, 3629 error 3630 }; 3631 } 3632 } 3633}; 3634var hasAuthParams = (location = window.location) => { 3635 let searchParams = new URLSearchParams(location.search); 3636 if ((searchParams.get("code") || searchParams.get("error")) && searchParams.get("state")) { 3637 return true; 3638 } 3639 searchParams = new URLSearchParams(location.hash.replace("#", "?")); 3640 if ((searchParams.get("code") || searchParams.get("error")) && searchParams.get("state")) { 3641 return true; 3642 } 3643 return false; 3644}; 3645var signinError = normalizeErrorFn("signinCallback", "Sign-in failed"); 3646var signoutError = normalizeErrorFn("signoutCallback", "Sign-out failed"); 3647var renewSilentError = normalizeErrorFn("renewSilent", "Renew silent failed"); 3648function normalizeError(error, fallbackMessage) { 3649 return { 3650 name: stringFieldOf(error, "name", () => "Error"), 3651 message: stringFieldOf(error, "message", () => fallbackMessage), 3652 stack: stringFieldOf(error, "stack", () => new Error().stack), 3653 innerError: error 3654 }; 3655} 3656function normalizeErrorFn(source, fallbackMessage) { 3657 return (error) => { 3658 return { 3659 ...normalizeError(error, fallbackMessage), 3660 source 3661 }; 3662 }; 3663} 3664function stringFieldOf(element, fieldName, or) { 3665 if (element && typeof element === "object") { 3666 const value = element[fieldName]; 3667 if (typeof value === "string") { 3668 return value; 3669 } 3670 } 3671 return or(); 3672} 3673var userManagerContextKeys = [ 3674 "clearStaleState", 3675 "querySessionStatus", 3676 "revokeTokens", 3677 "startSilentRenew", 3678 "stopSilentRenew" 3679]; 3680var navigatorKeys = [ 3681 "signinPopup", 3682 "signinSilent", 3683 "signinRedirect", 3684 "signinResourceOwnerCredentials", 3685 "signoutPopup", 3686 "signoutRedirect", 3687 "signoutSilent" 3688]; 3689var unsupportedEnvironment = (fnName) => () => { 3690 throw new Error( 3691 `UserManager#${fnName} was called from an unsupported context. If this is a server-rendered page, defer this call with useEffect() or pass a custom UserManager implementation.` 3692 ); 3693}; 3694var UserManagerImpl = typeof window === "undefined" ? null : UserManager; 3695var AuthProvider = (props) => { 3696 const { 3697 children, 3698 onSigninCallback, 3699 skipSigninCallback, 3700 matchSignoutCallback, 3701 onSignoutCallback, 3702 onRemoveUser, 3703 userManager: userManagerProp = null, 3704 ...userManagerSettings 3705 } = props; 3706 const [userManager] = import_react2.default.useState(() => { 3707 return userManagerProp != null ? userManagerProp : UserManagerImpl ? new UserManagerImpl(userManagerSettings) : { settings: userManagerSettings }; 3708 }); 3709 const [state, dispatch] = import_react2.default.useReducer(reducer, initialAuthState); 3710 const userManagerContext = import_react2.default.useMemo( 3711 () => Object.assign( 3712 { 3713 settings: userManager.settings, 3714 events: userManager.events 3715 }, 3716 Object.fromEntries( 3717 userManagerContextKeys.map((key) => { 3718 var _a, _b; 3719 return [ 3720 key, 3721 (_b = (_a = userManager[key]) == null ? void 0 : _a.bind(userManager)) != null ? _b : unsupportedEnvironment(key) 3722 ]; 3723 }) 3724 ), 3725 Object.fromEntries( 3726 navigatorKeys.map((key) => [ 3727 key, 3728 userManager[key] ? async (args) => { 3729 dispatch({ 3730 type: "NAVIGATOR_INIT", 3731 method: key 3732 }); 3733 try { 3734 return await userManager[key](args); 3735 } catch (error) { 3736 dispatch({ 3737 type: "ERROR", 3738 error: { 3739 ...normalizeError(error, `Unknown error while executing ${key}(...).`), 3740 source: key, 3741 args 3742 } 3743 }); 3744 return null; 3745 } finally { 3746 dispatch({ type: "NAVIGATOR_CLOSE" }); 3747 } 3748 } : unsupportedEnvironment(key) 3749 ]) 3750 ) 3751 ), 3752 [userManager] 3753 ); 3754 const didInitialize = import_react2.default.useRef(false); 3755 import_react2.default.useEffect(() => { 3756 if (!userManager || didInitialize.current) { 3757 return; 3758 } 3759 didInitialize.current = true; 3760 void (async () => { 3761 try { 3762 let user = null; 3763 if (hasAuthParams() && !skipSigninCallback) { 3764 user = await userManager.signinCallback(); 3765 if (onSigninCallback) await onSigninCallback(user); 3766 } 3767 user = !user ? await userManager.getUser() : user; 3768 dispatch({ type: "INITIALISED", user }); 3769 } catch (error) { 3770 dispatch({ 3771 type: "ERROR", 3772 error: signinError(error) 3773 }); 3774 } 3775 try { 3776 if (matchSignoutCallback && matchSignoutCallback(userManager.settings)) { 3777 const resp = await userManager.signoutCallback(); 3778 if (onSignoutCallback) await onSignoutCallback(resp); 3779 } 3780 } catch (error) { 3781 dispatch({ 3782 type: "ERROR", 3783 error: signoutError(error) 3784 }); 3785 } 3786 })(); 3787 }, [userManager, skipSigninCallback, onSigninCallback, onSignoutCallback, matchSignoutCallback]); 3788 import_react2.default.useEffect(() => { 3789 if (!userManager) return void 0; 3790 const handleUserLoaded = (user) => { 3791 dispatch({ type: "USER_LOADED", user }); 3792 }; 3793 userManager.events.addUserLoaded(handleUserLoaded); 3794 const handleUserUnloaded = () => { 3795 dispatch({ type: "USER_UNLOADED" }); 3796 }; 3797 userManager.events.addUserUnloaded(handleUserUnloaded); 3798 const handleUserSignedOut = () => { 3799 dispatch({ type: "USER_SIGNED_OUT" }); 3800 }; 3801 userManager.events.addUserSignedOut(handleUserSignedOut); 3802 const handleSilentRenewError = (error) => { 3803 dispatch({ 3804 type: "ERROR", 3805 error: renewSilentError(error) 3806 }); 3807 }; 3808 userManager.events.addSilentRenewError(handleSilentRenewError); 3809 return () => { 3810 userManager.events.removeUserLoaded(handleUserLoaded); 3811 userManager.events.removeUserUnloaded(handleUserUnloaded); 3812 userManager.events.removeUserSignedOut(handleUserSignedOut); 3813 userManager.events.removeSilentRenewError(handleSilentRenewError); 3814 }; 3815 }, [userManager]); 3816 const removeUser = import_react2.default.useCallback(async () => { 3817 if (!userManager) unsupportedEnvironment("removeUser"); 3818 await userManager.removeUser(); 3819 if (onRemoveUser) await onRemoveUser(); 3820 }, [userManager, onRemoveUser]); 3821 const contextValue = import_react2.default.useMemo(() => { 3822 return { 3823 ...state, 3824 ...userManagerContext, 3825 removeUser 3826 }; 3827 }, [state, userManagerContext, removeUser]); 3828 return import_react2.default.createElement(AuthContext.Provider, { value: contextValue }, children); 3829}; 3830var useAuth = () => { 3831 const context = import_react3.default.useContext(AuthContext); 3832 if (!context) { 3833 console.warn("AuthProvider context is undefined, please verify you are calling useAuth() as child of a <AuthProvider> component."); 3834 } 3835 return context; 3836}; 3837function useAutoSignin({ signinMethod = "signinRedirect", signinArgs } = {}) { 3838 const auth = useAuth(); 3839 const [hasTriedSignin, setHasTriedSignin] = import_react4.default.useState(false); 3840 const shouldAttemptSignin = import_react4.default.useMemo(() => !hasAuthParams() && !auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading && !hasTriedSignin, [auth.activeNavigator, auth.isAuthenticated, auth.isLoading, hasTriedSignin]); 3841 import_react4.default.useEffect(() => { 3842 if (shouldAttemptSignin) { 3843 switch (signinMethod) { 3844 case "signinPopup": 3845 void auth.signinPopup(signinArgs); 3846 break; 3847 case "signinRedirect": 3848 default: 3849 void auth.signinRedirect(signinArgs); 3850 break; 3851 } 3852 setHasTriedSignin(true); 3853 } 3854 }, [auth, hasTriedSignin, shouldAttemptSignin, signinMethod, signinArgs]); 3855 return { 3856 isLoading: auth.isLoading, 3857 isAuthenticated: auth.isAuthenticated, 3858 error: auth.error 3859 }; 3860} 3861function withAuth(Component) { 3862 const displayName = `withAuth(${Component.displayName || Component.name})`; 3863 const C = (props) => { 3864 const auth = useAuth(); 3865 return import_react5.default.createElement(Component, { ...props, auth }); 3866 }; 3867 C.displayName = displayName; 3868 return C; 3869} 3870var withAuthenticationRequired = (Component, options = {}) => { 3871 const { OnRedirecting = () => import_react6.default.createElement(import_react6.default.Fragment, null), onBeforeSignin, signinRedirectArgs } = options; 3872 const displayName = `withAuthenticationRequired(${Component.displayName || Component.name})`; 3873 const C = (props) => { 3874 const auth = useAuth(); 3875 import_react6.default.useEffect(() => { 3876 if (hasAuthParams() || auth.isLoading || auth.activeNavigator || auth.isAuthenticated) { 3877 return; 3878 } 3879 void (async () => { 3880 if (onBeforeSignin) await onBeforeSignin(); 3881 await auth.signinRedirect(signinRedirectArgs); 3882 })(); 3883 }, [auth.isLoading, auth.isAuthenticated, auth]); 3884 return auth.isAuthenticated ? import_react6.default.createElement(Component, { ...props }) : OnRedirecting(); 3885 }; 3886 C.displayName = displayName; 3887 return C; 3888}; 3889export { 3890 AuthContext, 3891 AuthProvider, 3892 hasAuthParams, 3893 useAuth, 3894 useAutoSignin, 3895 withAuth, 3896 withAuthenticationRequired 3897}; 3898//# sourceMappingURL=react-oidc-context.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.