g(x,c))a[d]=x,a[n]=c,d=n;else break a}}return b}\nfunction g(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}if(\"object\"===typeof performance&&\"function\"===typeof performance.now){var l=performance;exports.unstable_now=function(){return l.now()}}else{var p=Date,q=p.now();exports.unstable_now=function(){return p.now()-q}}var r=[],t=[],u=1,v=null,y=3,z=!1,A=!1,B=!1,D=\"function\"===typeof setTimeout?setTimeout:null,E=\"function\"===typeof clearTimeout?clearTimeout:null,F=\"undefined\"!==typeof setImmediate?setImmediate:null;\n\"undefined\"!==typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function G(a){for(var b=h(t);null!==b;){if(null===b.callback)k(t);else if(b.startTime<=a)k(t),b.sortIndex=b.expirationTime,f(r,b);else break;b=h(t)}}function H(a){B=!1;G(a);if(!A)if(null!==h(r))A=!0,I(J);else{var b=h(t);null!==b&&K(H,b.startTime-a)}}\nfunction J(a,b){A=!1;B&&(B=!1,E(L),L=-1);z=!0;var c=y;try{G(b);for(v=h(r);null!==v&&(!(v.expirationTime>b)||a&&!M());){var d=v.callback;if(\"function\"===typeof d){v.callback=null;y=v.priorityLevel;var e=d(v.expirationTime<=b);b=exports.unstable_now();\"function\"===typeof e?v.callback=e:v===h(r)&&k(r);G(b)}else k(r);v=h(r)}if(null!==v)var w=!0;else{var m=h(t);null!==m&&K(H,m.startTime-b);w=!1}return w}finally{v=null,y=c,z=!1}}var N=!1,O=null,L=-1,P=5,Q=-1;\nfunction M(){return exports.unstable_now()-Qa||125d?(a.sortIndex=c,f(t,a),null===h(r)&&a===h(t)&&(B?(E(L),L=-1):B=!0,K(H,c-d))):(a.sortIndex=e,f(r,a),A||z||(A=!0,I(J)));return a};\nexports.unstable_shouldYield=M;exports.unstable_wrapCallback=function(a){var b=y;return function(){var c=y;y=b;try{return a.apply(this,arguments)}finally{y=c}}};\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.min.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n","var camel2hyphen = function (str) {\n return str\n .replace(/[A-Z]/g, function (match) {\n return '-' + match.toLowerCase();\n })\n .toLowerCase();\n};\n\nmodule.exports = camel2hyphen;","\nmodule.exports = function () {\n var selection = document.getSelection();\n if (!selection.rangeCount) {\n return function () {};\n }\n var active = document.activeElement;\n\n var ranges = [];\n for (var i = 0; i < selection.rangeCount; i++) {\n ranges.push(selection.getRangeAt(i));\n }\n\n switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n case 'INPUT':\n case 'TEXTAREA':\n active.blur();\n break;\n\n default:\n active = null;\n break;\n }\n\n selection.removeAllRanges();\n return function () {\n selection.type === 'Caret' &&\n selection.removeAllRanges();\n\n if (!selection.rangeCount) {\n ranges.forEach(function(range) {\n selection.addRange(range);\n });\n }\n\n active &&\n active.focus();\n };\n};\n","/**\n * @license React\n * use-sync-external-store-shim.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var e=require(\"react\");function h(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}var k=\"function\"===typeof Object.is?Object.is:h,l=e.useState,m=e.useEffect,n=e.useLayoutEffect,p=e.useDebugValue;function q(a,b){var d=b(),f=l({inst:{value:d,getSnapshot:b}}),c=f[0].inst,g=f[1];n(function(){c.value=d;c.getSnapshot=b;r(c)&&g({inst:c})},[a,d,b]);m(function(){r(c)&&g({inst:c});return a(function(){r(c)&&g({inst:c})})},[a]);p(d);return d}\nfunction r(a){var b=a.getSnapshot;a=a.value;try{var d=b();return!k(a,d)}catch(f){return!0}}function t(a,b){return b()}var u=\"undefined\"===typeof window||\"undefined\"===typeof window.document||\"undefined\"===typeof window.document.createElement?t:q;exports.useSyncExternalStore=void 0!==e.useSyncExternalStore?e.useSyncExternalStore:u;\n","/**\n * @license React\n * use-sync-external-store-shim/with-selector.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var h=require(\"react\"),n=require(\"use-sync-external-store/shim\");function p(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}var q=\"function\"===typeof Object.is?Object.is:p,r=n.useSyncExternalStore,t=h.useRef,u=h.useEffect,v=h.useMemo,w=h.useDebugValue;\nexports.useSyncExternalStoreWithSelector=function(a,b,e,l,g){var c=t(null);if(null===c.current){var f={hasValue:!1,value:null};c.current=f}else f=c.current;c=v(function(){function a(a){if(!c){c=!0;d=a;a=l(a);if(void 0!==g&&f.hasValue){var b=f.value;if(g(b,a))return k=b}return k=a}b=k;if(q(d,a))return b;var e=l(a);if(void 0!==g&&g(b,e))return b;d=a;return k=e}var c=!1,d,k,m=void 0===e?null:e;return[function(){return a(b())},null===m?void 0:function(){return a(m())}]},[b,e,l,g]);var d=r(a,c[0],c[1]);\nu(function(){f.hasValue=!0;f.value=d},[d]);w(d);return d};\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('../cjs/use-sync-external-store-shim.production.min.js');\n} else {\n module.exports = require('../cjs/use-sync-external-store-shim.development.js');\n}\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('../cjs/use-sync-external-store-shim/with-selector.production.min.js');\n} else {\n module.exports = require('../cjs/use-sync-external-store-shim/with-selector.development.js');\n}\n","function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];\n return arr2;\n}\nmodule.exports = _arrayLikeToArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\nmodule.exports = _arrayWithHoles, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var arrayLikeToArray = require(\"./arrayLikeToArray.js\");\nfunction _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) return arrayLikeToArray(arr);\n}\nmodule.exports = _arrayWithoutHoles, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n return self;\n}\nmodule.exports = _assertThisInitialized, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\nfunction _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n _next(undefined);\n });\n };\n}\nmodule.exports = _asyncToGenerator, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\nmodule.exports = _classCallCheck, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var toPropertyKey = require(\"./toPropertyKey.js\");\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, toPropertyKey(descriptor.key), descriptor);\n }\n}\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n Object.defineProperty(Constructor, \"prototype\", {\n writable: false\n });\n return Constructor;\n}\nmodule.exports = _createClass, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var getPrototypeOf = require(\"./getPrototypeOf.js\");\nvar isNativeReflectConstruct = require(\"./isNativeReflectConstruct.js\");\nvar possibleConstructorReturn = require(\"./possibleConstructorReturn.js\");\nfunction _createSuper(Derived) {\n var hasNativeReflectConstruct = isNativeReflectConstruct();\n return function _createSuperInternal() {\n var Super = getPrototypeOf(Derived),\n result;\n if (hasNativeReflectConstruct) {\n var NewTarget = getPrototypeOf(this).constructor;\n result = Reflect.construct(Super, arguments, NewTarget);\n } else {\n result = Super.apply(this, arguments);\n }\n return possibleConstructorReturn(this, result);\n };\n}\nmodule.exports = _createSuper, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var toPropertyKey = require(\"./toPropertyKey.js\");\nfunction _defineProperty(obj, key, value) {\n key = toPropertyKey(key);\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n return obj;\n}\nmodule.exports = _defineProperty, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _extends() {\n module.exports = _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n }, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;\n return _extends.apply(this, arguments);\n}\nmodule.exports = _extends, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _getPrototypeOf(o) {\n module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n }, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;\n return _getPrototypeOf(o);\n}\nmodule.exports = _getPrototypeOf, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var setPrototypeOf = require(\"./setPrototypeOf.js\");\nfunction _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n Object.defineProperty(subClass, \"prototype\", {\n writable: false\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}\nmodule.exports = _inherits, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _interopRequireDefault(obj) {\n return obj && obj.__esModule ? obj : {\n \"default\": obj\n };\n}\nmodule.exports = _interopRequireDefault, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var _typeof = require(\"./typeof.js\")[\"default\"];\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interopRequireWildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) {\n return obj;\n }\n if (obj === null || _typeof(obj) !== \"object\" && typeof obj !== \"function\") {\n return {\n \"default\": obj\n };\n }\n var cache = _getRequireWildcardCache(nodeInterop);\n if (cache && cache.has(obj)) {\n return cache.get(obj);\n }\n var newObj = {};\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) {\n Object.defineProperty(newObj, key, desc);\n } else {\n newObj[key] = obj[key];\n }\n }\n }\n newObj[\"default\"] = obj;\n if (cache) {\n cache.set(obj, newObj);\n }\n return newObj;\n}\nmodule.exports = _interopRequireWildcard, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _isNativeReflectConstruct() {\n if (typeof Reflect === \"undefined\" || !Reflect.construct) return false;\n if (Reflect.construct.sham) return false;\n if (typeof Proxy === \"function\") return true;\n try {\n Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));\n return true;\n } catch (e) {\n return false;\n }\n}\nmodule.exports = _isNativeReflectConstruct, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _iterableToArray(iter) {\n if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter);\n}\nmodule.exports = _iterableToArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _iterableToArrayLimit(r, l) {\n var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (null != t) {\n var e,\n n,\n i,\n u,\n a = [],\n f = !0,\n o = !1;\n try {\n if (i = (t = t.call(r)).next, 0 === l) {\n if (Object(t) !== t) return;\n f = !1;\n } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n } catch (r) {\n o = !0, n = r;\n } finally {\n try {\n if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return;\n } finally {\n if (o) throw n;\n }\n }\n return a;\n }\n}\nmodule.exports = _iterableToArrayLimit, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nmodule.exports = _nonIterableRest, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nmodule.exports = _nonIterableSpread, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var defineProperty = require(\"./defineProperty.js\");\nfunction ownKeys(e, r) {\n var t = Object.keys(e);\n if (Object.getOwnPropertySymbols) {\n var o = Object.getOwnPropertySymbols(e);\n r && (o = o.filter(function (r) {\n return Object.getOwnPropertyDescriptor(e, r).enumerable;\n })), t.push.apply(t, o);\n }\n return t;\n}\nfunction _objectSpread2(e) {\n for (var r = 1; r < arguments.length; r++) {\n var t = null != arguments[r] ? arguments[r] : {};\n r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {\n defineProperty(e, r, t[r]);\n }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {\n Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));\n });\n }\n return e;\n}\nmodule.exports = _objectSpread2, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var objectWithoutPropertiesLoose = require(\"./objectWithoutPropertiesLoose.js\");\nfunction _objectWithoutProperties(source, excluded) {\n if (source == null) return {};\n var target = objectWithoutPropertiesLoose(source, excluded);\n var key, i;\n if (Object.getOwnPropertySymbols) {\n var sourceSymbolKeys = Object.getOwnPropertySymbols(source);\n for (i = 0; i < sourceSymbolKeys.length; i++) {\n key = sourceSymbolKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n target[key] = source[key];\n }\n }\n return target;\n}\nmodule.exports = _objectWithoutProperties, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n return target;\n}\nmodule.exports = _objectWithoutPropertiesLoose, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var _typeof = require(\"./typeof.js\")[\"default\"];\nvar assertThisInitialized = require(\"./assertThisInitialized.js\");\nfunction _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n } else if (call !== void 0) {\n throw new TypeError(\"Derived constructors may only return object or undefined\");\n }\n return assertThisInitialized(self);\n}\nmodule.exports = _possibleConstructorReturn, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var _typeof = require(\"./typeof.js\")[\"default\"];\nfunction _regeneratorRuntime() {\n \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */\n module.exports = _regeneratorRuntime = function _regeneratorRuntime() {\n return e;\n }, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;\n var t,\n e = {},\n r = Object.prototype,\n n = r.hasOwnProperty,\n o = Object.defineProperty || function (t, e, r) {\n t[e] = r.value;\n },\n i = \"function\" == typeof Symbol ? Symbol : {},\n a = i.iterator || \"@@iterator\",\n c = i.asyncIterator || \"@@asyncIterator\",\n u = i.toStringTag || \"@@toStringTag\";\n function define(t, e, r) {\n return Object.defineProperty(t, e, {\n value: r,\n enumerable: !0,\n configurable: !0,\n writable: !0\n }), t[e];\n }\n try {\n define({}, \"\");\n } catch (t) {\n define = function define(t, e, r) {\n return t[e] = r;\n };\n }\n function wrap(t, e, r, n) {\n var i = e && e.prototype instanceof Generator ? e : Generator,\n a = Object.create(i.prototype),\n c = new Context(n || []);\n return o(a, \"_invoke\", {\n value: makeInvokeMethod(t, r, c)\n }), a;\n }\n function tryCatch(t, e, r) {\n try {\n return {\n type: \"normal\",\n arg: t.call(e, r)\n };\n } catch (t) {\n return {\n type: \"throw\",\n arg: t\n };\n }\n }\n e.wrap = wrap;\n var h = \"suspendedStart\",\n l = \"suspendedYield\",\n f = \"executing\",\n s = \"completed\",\n y = {};\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n var p = {};\n define(p, a, function () {\n return this;\n });\n var d = Object.getPrototypeOf,\n v = d && d(d(values([])));\n v && v !== r && n.call(v, a) && (p = v);\n var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);\n function defineIteratorMethods(t) {\n [\"next\", \"throw\", \"return\"].forEach(function (e) {\n define(t, e, function (t) {\n return this._invoke(e, t);\n });\n });\n }\n function AsyncIterator(t, e) {\n function invoke(r, o, i, a) {\n var c = tryCatch(t[r], t, o);\n if (\"throw\" !== c.type) {\n var u = c.arg,\n h = u.value;\n return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) {\n invoke(\"next\", t, i, a);\n }, function (t) {\n invoke(\"throw\", t, i, a);\n }) : e.resolve(h).then(function (t) {\n u.value = t, i(u);\n }, function (t) {\n return invoke(\"throw\", t, i, a);\n });\n }\n a(c.arg);\n }\n var r;\n o(this, \"_invoke\", {\n value: function value(t, n) {\n function callInvokeWithMethodAndArg() {\n return new e(function (e, r) {\n invoke(t, n, e, r);\n });\n }\n return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();\n }\n });\n }\n function makeInvokeMethod(e, r, n) {\n var o = h;\n return function (i, a) {\n if (o === f) throw new Error(\"Generator is already running\");\n if (o === s) {\n if (\"throw\" === i) throw a;\n return {\n value: t,\n done: !0\n };\n }\n for (n.method = i, n.arg = a;;) {\n var c = n.delegate;\n if (c) {\n var u = maybeInvokeDelegate(c, n);\n if (u) {\n if (u === y) continue;\n return u;\n }\n }\n if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) {\n if (o === h) throw o = s, n.arg;\n n.dispatchException(n.arg);\n } else \"return\" === n.method && n.abrupt(\"return\", n.arg);\n o = f;\n var p = tryCatch(e, r, n);\n if (\"normal\" === p.type) {\n if (o = n.done ? s : l, p.arg === y) continue;\n return {\n value: p.arg,\n done: n.done\n };\n }\n \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg);\n }\n };\n }\n function maybeInvokeDelegate(e, r) {\n var n = r.method,\n o = e.iterator[n];\n if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y;\n var i = tryCatch(o, e.iterator, r.arg);\n if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y;\n var a = i.arg;\n return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y);\n }\n function pushTryEntry(t) {\n var e = {\n tryLoc: t[0]\n };\n 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);\n }\n function resetTryEntry(t) {\n var e = t.completion || {};\n e.type = \"normal\", delete e.arg, t.completion = e;\n }\n function Context(t) {\n this.tryEntries = [{\n tryLoc: \"root\"\n }], t.forEach(pushTryEntry, this), this.reset(!0);\n }\n function values(e) {\n if (e || \"\" === e) {\n var r = e[a];\n if (r) return r.call(e);\n if (\"function\" == typeof e.next) return e;\n if (!isNaN(e.length)) {\n var o = -1,\n i = function next() {\n for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;\n return next.value = t, next.done = !0, next;\n };\n return i.next = i;\n }\n }\n throw new TypeError(_typeof(e) + \" is not iterable\");\n }\n return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", {\n value: GeneratorFunctionPrototype,\n configurable: !0\n }), o(GeneratorFunctionPrototype, \"constructor\", {\n value: GeneratorFunction,\n configurable: !0\n }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) {\n var e = \"function\" == typeof t && t.constructor;\n return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name));\n }, e.mark = function (t) {\n return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t;\n }, e.awrap = function (t) {\n return {\n __await: t\n };\n }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {\n return this;\n }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {\n void 0 === i && (i = Promise);\n var a = new AsyncIterator(wrap(t, r, n, o), i);\n return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {\n return t.done ? t.value : a.next();\n });\n }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () {\n return this;\n }), define(g, \"toString\", function () {\n return \"[object Generator]\";\n }), e.keys = function (t) {\n var e = Object(t),\n r = [];\n for (var n in e) r.push(n);\n return r.reverse(), function next() {\n for (; r.length;) {\n var t = r.pop();\n if (t in e) return next.value = t, next.done = !1, next;\n }\n return next.done = !0, next;\n };\n }, e.values = values, Context.prototype = {\n constructor: Context,\n reset: function reset(e) {\n if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);\n },\n stop: function stop() {\n this.done = !0;\n var t = this.tryEntries[0].completion;\n if (\"throw\" === t.type) throw t.arg;\n return this.rval;\n },\n dispatchException: function dispatchException(e) {\n if (this.done) throw e;\n var r = this;\n function handle(n, o) {\n return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o;\n }\n for (var o = this.tryEntries.length - 1; o >= 0; --o) {\n var i = this.tryEntries[o],\n a = i.completion;\n if (\"root\" === i.tryLoc) return handle(\"end\");\n if (i.tryLoc <= this.prev) {\n var c = n.call(i, \"catchLoc\"),\n u = n.call(i, \"finallyLoc\");\n if (c && u) {\n if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);\n if (this.prev < i.finallyLoc) return handle(i.finallyLoc);\n } else if (c) {\n if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);\n } else {\n if (!u) throw new Error(\"try statement without catch or finally\");\n if (this.prev < i.finallyLoc) return handle(i.finallyLoc);\n }\n }\n }\n },\n abrupt: function abrupt(t, e) {\n for (var r = this.tryEntries.length - 1; r >= 0; --r) {\n var o = this.tryEntries[r];\n if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) {\n var i = o;\n break;\n }\n }\n i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);\n var a = i ? i.completion : {};\n return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a);\n },\n complete: function complete(t, e) {\n if (\"throw\" === t.type) throw t.arg;\n return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y;\n },\n finish: function finish(t) {\n for (var e = this.tryEntries.length - 1; e >= 0; --e) {\n var r = this.tryEntries[e];\n if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;\n }\n },\n \"catch\": function _catch(t) {\n for (var e = this.tryEntries.length - 1; e >= 0; --e) {\n var r = this.tryEntries[e];\n if (r.tryLoc === t) {\n var n = r.completion;\n if (\"throw\" === n.type) {\n var o = n.arg;\n resetTryEntry(r);\n }\n return o;\n }\n }\n throw new Error(\"illegal catch attempt\");\n },\n delegateYield: function delegateYield(e, r, n) {\n return this.delegate = {\n iterator: values(e),\n resultName: r,\n nextLoc: n\n }, \"next\" === this.method && (this.arg = t), y;\n }\n }, e;\n}\nmodule.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _setPrototypeOf(o, p) {\n module.exports = _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n }, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;\n return _setPrototypeOf(o, p);\n}\nmodule.exports = _setPrototypeOf, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var arrayWithHoles = require(\"./arrayWithHoles.js\");\nvar iterableToArrayLimit = require(\"./iterableToArrayLimit.js\");\nvar unsupportedIterableToArray = require(\"./unsupportedIterableToArray.js\");\nvar nonIterableRest = require(\"./nonIterableRest.js\");\nfunction _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();\n}\nmodule.exports = _slicedToArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var arrayWithHoles = require(\"./arrayWithHoles.js\");\nvar iterableToArray = require(\"./iterableToArray.js\");\nvar unsupportedIterableToArray = require(\"./unsupportedIterableToArray.js\");\nvar nonIterableRest = require(\"./nonIterableRest.js\");\nfunction _toArray(arr) {\n return arrayWithHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableRest();\n}\nmodule.exports = _toArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var arrayWithoutHoles = require(\"./arrayWithoutHoles.js\");\nvar iterableToArray = require(\"./iterableToArray.js\");\nvar unsupportedIterableToArray = require(\"./unsupportedIterableToArray.js\");\nvar nonIterableSpread = require(\"./nonIterableSpread.js\");\nfunction _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableSpread();\n}\nmodule.exports = _toConsumableArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var _typeof = require(\"./typeof.js\")[\"default\"];\nfunction _toPrimitive(input, hint) {\n if (_typeof(input) !== \"object\" || input === null) return input;\n var prim = input[Symbol.toPrimitive];\n if (prim !== undefined) {\n var res = prim.call(input, hint || \"default\");\n if (_typeof(res) !== \"object\") return res;\n throw new TypeError(\"@@toPrimitive must return a primitive value.\");\n }\n return (hint === \"string\" ? String : Number)(input);\n}\nmodule.exports = _toPrimitive, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var _typeof = require(\"./typeof.js\")[\"default\"];\nvar toPrimitive = require(\"./toPrimitive.js\");\nfunction _toPropertyKey(arg) {\n var key = toPrimitive(arg, \"string\");\n return _typeof(key) === \"symbol\" ? key : String(key);\n}\nmodule.exports = _toPropertyKey, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return (module.exports = _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, module.exports.__esModule = true, module.exports[\"default\"] = module.exports), _typeof(o);\n}\nmodule.exports = _typeof, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","var arrayLikeToArray = require(\"./arrayLikeToArray.js\");\nfunction _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}\nmodule.exports = _unsupportedIterableToArray, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)\n * are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,\n * as-is, to `callback` when the throttled-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds\n * while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed\n * one final time after the last throttled-function call. (After the throttled-function has not been called for\n * `delay` milliseconds, the internal counter is reset).\n * @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback\n * immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that\n * callback will never executed if both noLeading = true and noTrailing = true.\n * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is\n * false (at end), schedule `callback` to execute after `delay` ms.\n *\n * @returns {Function} A new, throttled, function.\n */\nexport default function (delay, callback, options) {\n\tconst {\n\t\tnoTrailing = false,\n\t\tnoLeading = false,\n\t\tdebounceMode = undefined\n\t} = options || {};\n\t/*\n\t * After wrapper has stopped being called, this timeout ensures that\n\t * `callback` is executed at the proper times in `throttle` and `end`\n\t * debounce modes.\n\t */\n\tlet timeoutID;\n\tlet cancelled = false;\n\n\t// Keep track of the last time `callback` was executed.\n\tlet lastExec = 0;\n\n\t// Function to clear existing timeout\n\tfunction clearExistingTimeout() {\n\t\tif (timeoutID) {\n\t\t\tclearTimeout(timeoutID);\n\t\t}\n\t}\n\n\t// Function to cancel next exec\n\tfunction cancel(options) {\n\t\tconst { upcomingOnly = false } = options || {};\n\t\tclearExistingTimeout();\n\t\tcancelled = !upcomingOnly;\n\t}\n\n\t/*\n\t * The `wrapper` function encapsulates all of the throttling / debouncing\n\t * functionality and when executed will limit the rate at which `callback`\n\t * is executed.\n\t */\n\tfunction wrapper(...arguments_) {\n\t\tlet self = this;\n\t\tlet elapsed = Date.now() - lastExec;\n\n\t\tif (cancelled) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Execute `callback` and update the `lastExec` timestamp.\n\t\tfunction exec() {\n\t\t\tlastExec = Date.now();\n\t\t\tcallback.apply(self, arguments_);\n\t\t}\n\n\t\t/*\n\t\t * If `debounceMode` is true (at begin) this is used to clear the flag\n\t\t * to allow future `callback` executions.\n\t\t */\n\t\tfunction clear() {\n\t\t\ttimeoutID = undefined;\n\t\t}\n\n\t\tif (!noLeading && debounceMode && !timeoutID) {\n\t\t\t/*\n\t\t\t * Since `wrapper` is being called for the first time and\n\t\t\t * `debounceMode` is true (at begin), execute `callback`\n\t\t\t * and noLeading != true.\n\t\t\t */\n\t\t\texec();\n\t\t}\n\n\t\tclearExistingTimeout();\n\n\t\tif (debounceMode === undefined && elapsed > delay) {\n\t\t\tif (noLeading) {\n\t\t\t\t/*\n\t\t\t\t * In throttle mode with noLeading, if `delay` time has\n\t\t\t\t * been exceeded, update `lastExec` and schedule `callback`\n\t\t\t\t * to execute after `delay` ms.\n\t\t\t\t */\n\t\t\t\tlastExec = Date.now();\n\t\t\t\tif (!noTrailing) {\n\t\t\t\t\ttimeoutID = setTimeout(debounceMode ? clear : exec, delay);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * In throttle mode without noLeading, if `delay` time has been exceeded, execute\n\t\t\t\t * `callback`.\n\t\t\t\t */\n\t\t\t\texec();\n\t\t\t}\n\t\t} else if (noTrailing !== true) {\n\t\t\t/*\n\t\t\t * In trailing throttle mode, since `delay` time has not been\n\t\t\t * exceeded, schedule `callback` to execute `delay` ms after most\n\t\t\t * recent execution.\n\t\t\t *\n\t\t\t * If `debounceMode` is true (at begin), schedule `clear` to execute\n\t\t\t * after `delay` ms.\n\t\t\t *\n\t\t\t * If `debounceMode` is false (at end), schedule `callback` to\n\t\t\t * execute after `delay` ms.\n\t\t\t */\n\t\t\ttimeoutID = setTimeout(\n\t\t\t\tdebounceMode ? clear : exec,\n\t\t\t\tdebounceMode === undefined ? delay - elapsed : delay\n\t\t\t);\n\t\t}\n\t}\n\n\twrapper.cancel = cancel;\n\n\t// Return the wrapper function.\n\treturn wrapper;\n}\n","/* eslint-disable no-undefined */\n\nimport throttle from './throttle.js';\n\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n *\n * @returns {Function} A new, debounced function.\n */\nexport default function (delay, callback, options) {\n\tconst { atBegin = false } = options || {};\n\treturn throttle(delay, callback, { debounceMode: atBegin !== false });\n}\n","export default function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];\n return arr2;\n}","export default function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}","export default function _assertThisInitialized(self) {\n if (self === void 0) {\n throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n }\n return self;\n}","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\nexport default function _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n _next(undefined);\n });\n };\n}","export default function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}","import toPropertyKey from \"./toPropertyKey.js\";\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, toPropertyKey(descriptor.key), descriptor);\n }\n}\nexport default function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n Object.defineProperty(Constructor, \"prototype\", {\n writable: false\n });\n return Constructor;\n}","import unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nexport default function _createForOfIteratorHelper(o, allowArrayLike) {\n var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"];\n if (!it) {\n if (Array.isArray(o) || (it = unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") {\n if (it) o = it;\n var i = 0;\n var F = function F() {};\n return {\n s: F,\n n: function n() {\n if (i >= o.length) return {\n done: true\n };\n return {\n done: false,\n value: o[i++]\n };\n },\n e: function e(_e) {\n throw _e;\n },\n f: F\n };\n }\n throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n }\n var normalCompletion = true,\n didErr = false,\n err;\n return {\n s: function s() {\n it = it.call(o);\n },\n n: function n() {\n var step = it.next();\n normalCompletion = step.done;\n return step;\n },\n e: function e(_e2) {\n didErr = true;\n err = _e2;\n },\n f: function f() {\n try {\n if (!normalCompletion && it[\"return\"] != null) it[\"return\"]();\n } finally {\n if (didErr) throw err;\n }\n }\n };\n}","import _typeof from \"./typeof.js\";\nimport assertThisInitialized from \"./assertThisInitialized.js\";\nexport default function _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n } else if (call !== void 0) {\n throw new TypeError(\"Derived constructors may only return object or undefined\");\n }\n return assertThisInitialized(self);\n}","import getPrototypeOf from \"./getPrototypeOf.js\";\nimport isNativeReflectConstruct from \"./isNativeReflectConstruct.js\";\nimport possibleConstructorReturn from \"./possibleConstructorReturn.js\";\nexport default function _createSuper(Derived) {\n var hasNativeReflectConstruct = isNativeReflectConstruct();\n return function _createSuperInternal() {\n var Super = getPrototypeOf(Derived),\n result;\n if (hasNativeReflectConstruct) {\n var NewTarget = getPrototypeOf(this).constructor;\n result = Reflect.construct(Super, arguments, NewTarget);\n } else {\n result = Super.apply(this, arguments);\n }\n return possibleConstructorReturn(this, result);\n };\n}","import toPropertyKey from \"./toPropertyKey.js\";\nexport default function _defineProperty(obj, key, value) {\n key = toPropertyKey(key);\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n return obj;\n}","export default function _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}","export default function _getPrototypeOf(o) {\n _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n Object.defineProperty(subClass, \"prototype\", {\n writable: false\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}","export default function _isNativeReflectConstruct() {\n if (typeof Reflect === \"undefined\" || !Reflect.construct) return false;\n if (Reflect.construct.sham) return false;\n if (typeof Proxy === \"function\") return true;\n try {\n Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));\n return true;\n } catch (e) {\n return false;\n }\n}","export default function _iterableToArray(iter) {\n if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter);\n}","export default function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}","import defineProperty from \"./defineProperty.js\";\nfunction ownKeys(e, r) {\n var t = Object.keys(e);\n if (Object.getOwnPropertySymbols) {\n var o = Object.getOwnPropertySymbols(e);\n r && (o = o.filter(function (r) {\n return Object.getOwnPropertyDescriptor(e, r).enumerable;\n })), t.push.apply(t, o);\n }\n return t;\n}\nexport default function _objectSpread2(e) {\n for (var r = 1; r < arguments.length; r++) {\n var t = null != arguments[r] ? arguments[r] : {};\n r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {\n defineProperty(e, r, t[r]);\n }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {\n Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));\n });\n }\n return e;\n}","import objectWithoutPropertiesLoose from \"./objectWithoutPropertiesLoose.js\";\nexport default function _objectWithoutProperties(source, excluded) {\n if (source == null) return {};\n var target = objectWithoutPropertiesLoose(source, excluded);\n var key, i;\n if (Object.getOwnPropertySymbols) {\n var sourceSymbolKeys = Object.getOwnPropertySymbols(source);\n for (i = 0; i < sourceSymbolKeys.length; i++) {\n key = sourceSymbolKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n target[key] = source[key];\n }\n }\n return target;\n}","export default function _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n return target;\n}","import _typeof from \"./typeof.js\";\nexport default function _regeneratorRuntime() {\n \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */\n _regeneratorRuntime = function _regeneratorRuntime() {\n return e;\n };\n var t,\n e = {},\n r = Object.prototype,\n n = r.hasOwnProperty,\n o = Object.defineProperty || function (t, e, r) {\n t[e] = r.value;\n },\n i = \"function\" == typeof Symbol ? Symbol : {},\n a = i.iterator || \"@@iterator\",\n c = i.asyncIterator || \"@@asyncIterator\",\n u = i.toStringTag || \"@@toStringTag\";\n function define(t, e, r) {\n return Object.defineProperty(t, e, {\n value: r,\n enumerable: !0,\n configurable: !0,\n writable: !0\n }), t[e];\n }\n try {\n define({}, \"\");\n } catch (t) {\n define = function define(t, e, r) {\n return t[e] = r;\n };\n }\n function wrap(t, e, r, n) {\n var i = e && e.prototype instanceof Generator ? e : Generator,\n a = Object.create(i.prototype),\n c = new Context(n || []);\n return o(a, \"_invoke\", {\n value: makeInvokeMethod(t, r, c)\n }), a;\n }\n function tryCatch(t, e, r) {\n try {\n return {\n type: \"normal\",\n arg: t.call(e, r)\n };\n } catch (t) {\n return {\n type: \"throw\",\n arg: t\n };\n }\n }\n e.wrap = wrap;\n var h = \"suspendedStart\",\n l = \"suspendedYield\",\n f = \"executing\",\n s = \"completed\",\n y = {};\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n var p = {};\n define(p, a, function () {\n return this;\n });\n var d = Object.getPrototypeOf,\n v = d && d(d(values([])));\n v && v !== r && n.call(v, a) && (p = v);\n var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);\n function defineIteratorMethods(t) {\n [\"next\", \"throw\", \"return\"].forEach(function (e) {\n define(t, e, function (t) {\n return this._invoke(e, t);\n });\n });\n }\n function AsyncIterator(t, e) {\n function invoke(r, o, i, a) {\n var c = tryCatch(t[r], t, o);\n if (\"throw\" !== c.type) {\n var u = c.arg,\n h = u.value;\n return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) {\n invoke(\"next\", t, i, a);\n }, function (t) {\n invoke(\"throw\", t, i, a);\n }) : e.resolve(h).then(function (t) {\n u.value = t, i(u);\n }, function (t) {\n return invoke(\"throw\", t, i, a);\n });\n }\n a(c.arg);\n }\n var r;\n o(this, \"_invoke\", {\n value: function value(t, n) {\n function callInvokeWithMethodAndArg() {\n return new e(function (e, r) {\n invoke(t, n, e, r);\n });\n }\n return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();\n }\n });\n }\n function makeInvokeMethod(e, r, n) {\n var o = h;\n return function (i, a) {\n if (o === f) throw new Error(\"Generator is already running\");\n if (o === s) {\n if (\"throw\" === i) throw a;\n return {\n value: t,\n done: !0\n };\n }\n for (n.method = i, n.arg = a;;) {\n var c = n.delegate;\n if (c) {\n var u = maybeInvokeDelegate(c, n);\n if (u) {\n if (u === y) continue;\n return u;\n }\n }\n if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) {\n if (o === h) throw o = s, n.arg;\n n.dispatchException(n.arg);\n } else \"return\" === n.method && n.abrupt(\"return\", n.arg);\n o = f;\n var p = tryCatch(e, r, n);\n if (\"normal\" === p.type) {\n if (o = n.done ? s : l, p.arg === y) continue;\n return {\n value: p.arg,\n done: n.done\n };\n }\n \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg);\n }\n };\n }\n function maybeInvokeDelegate(e, r) {\n var n = r.method,\n o = e.iterator[n];\n if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y;\n var i = tryCatch(o, e.iterator, r.arg);\n if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y;\n var a = i.arg;\n return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y);\n }\n function pushTryEntry(t) {\n var e = {\n tryLoc: t[0]\n };\n 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);\n }\n function resetTryEntry(t) {\n var e = t.completion || {};\n e.type = \"normal\", delete e.arg, t.completion = e;\n }\n function Context(t) {\n this.tryEntries = [{\n tryLoc: \"root\"\n }], t.forEach(pushTryEntry, this), this.reset(!0);\n }\n function values(e) {\n if (e || \"\" === e) {\n var r = e[a];\n if (r) return r.call(e);\n if (\"function\" == typeof e.next) return e;\n if (!isNaN(e.length)) {\n var o = -1,\n i = function next() {\n for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;\n return next.value = t, next.done = !0, next;\n };\n return i.next = i;\n }\n }\n throw new TypeError(_typeof(e) + \" is not iterable\");\n }\n return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", {\n value: GeneratorFunctionPrototype,\n configurable: !0\n }), o(GeneratorFunctionPrototype, \"constructor\", {\n value: GeneratorFunction,\n configurable: !0\n }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) {\n var e = \"function\" == typeof t && t.constructor;\n return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name));\n }, e.mark = function (t) {\n return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t;\n }, e.awrap = function (t) {\n return {\n __await: t\n };\n }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {\n return this;\n }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {\n void 0 === i && (i = Promise);\n var a = new AsyncIterator(wrap(t, r, n, o), i);\n return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {\n return t.done ? t.value : a.next();\n });\n }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () {\n return this;\n }), define(g, \"toString\", function () {\n return \"[object Generator]\";\n }), e.keys = function (t) {\n var e = Object(t),\n r = [];\n for (var n in e) r.push(n);\n return r.reverse(), function next() {\n for (; r.length;) {\n var t = r.pop();\n if (t in e) return next.value = t, next.done = !1, next;\n }\n return next.done = !0, next;\n };\n }, e.values = values, Context.prototype = {\n constructor: Context,\n reset: function reset(e) {\n if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);\n },\n stop: function stop() {\n this.done = !0;\n var t = this.tryEntries[0].completion;\n if (\"throw\" === t.type) throw t.arg;\n return this.rval;\n },\n dispatchException: function dispatchException(e) {\n if (this.done) throw e;\n var r = this;\n function handle(n, o) {\n return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o;\n }\n for (var o = this.tryEntries.length - 1; o >= 0; --o) {\n var i = this.tryEntries[o],\n a = i.completion;\n if (\"root\" === i.tryLoc) return handle(\"end\");\n if (i.tryLoc <= this.prev) {\n var c = n.call(i, \"catchLoc\"),\n u = n.call(i, \"finallyLoc\");\n if (c && u) {\n if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);\n if (this.prev < i.finallyLoc) return handle(i.finallyLoc);\n } else if (c) {\n if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);\n } else {\n if (!u) throw new Error(\"try statement without catch or finally\");\n if (this.prev < i.finallyLoc) return handle(i.finallyLoc);\n }\n }\n }\n },\n abrupt: function abrupt(t, e) {\n for (var r = this.tryEntries.length - 1; r >= 0; --r) {\n var o = this.tryEntries[r];\n if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) {\n var i = o;\n break;\n }\n }\n i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);\n var a = i ? i.completion : {};\n return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a);\n },\n complete: function complete(t, e) {\n if (\"throw\" === t.type) throw t.arg;\n return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y;\n },\n finish: function finish(t) {\n for (var e = this.tryEntries.length - 1; e >= 0; --e) {\n var r = this.tryEntries[e];\n if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;\n }\n },\n \"catch\": function _catch(t) {\n for (var e = this.tryEntries.length - 1; e >= 0; --e) {\n var r = this.tryEntries[e];\n if (r.tryLoc === t) {\n var n = r.completion;\n if (\"throw\" === n.type) {\n var o = n.arg;\n resetTryEntry(r);\n }\n return o;\n }\n }\n throw new Error(\"illegal catch attempt\");\n },\n delegateYield: function delegateYield(e, r, n) {\n return this.delegate = {\n iterator: values(e),\n resultName: r,\n nextLoc: n\n }, \"next\" === this.method && (this.arg = t), y;\n }\n }, e;\n}","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n return _setPrototypeOf(o, p);\n}","import arrayWithHoles from \"./arrayWithHoles.js\";\nimport iterableToArrayLimit from \"./iterableToArrayLimit.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableRest from \"./nonIterableRest.js\";\nexport default function _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();\n}","export default function _iterableToArrayLimit(r, l) {\n var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (null != t) {\n var e,\n n,\n i,\n u,\n a = [],\n f = !0,\n o = !1;\n try {\n if (i = (t = t.call(r)).next, 0 === l) {\n if (Object(t) !== t) return;\n f = !1;\n } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n } catch (r) {\n o = !0, n = r;\n } finally {\n try {\n if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return;\n } finally {\n if (o) throw n;\n }\n }\n return a;\n }\n}","import arrayWithHoles from \"./arrayWithHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableRest from \"./nonIterableRest.js\";\nexport default function _toArray(arr) {\n return arrayWithHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableRest();\n}","import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nexport default function _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableSpread();\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) return arrayLikeToArray(arr);\n}","export default function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}","import _typeof from \"./typeof.js\";\nimport toPrimitive from \"./toPrimitive.js\";\nexport default function _toPropertyKey(arg) {\n var key = toPrimitive(arg, \"string\");\n return _typeof(key) === \"symbol\" ? key : String(key);\n}","import _typeof from \"./typeof.js\";\nexport default function _toPrimitive(input, hint) {\n if (_typeof(input) !== \"object\" || input === null) return input;\n var prim = input[Symbol.toPrimitive];\n if (prim !== undefined) {\n var res = prim.call(input, hint || \"default\");\n if (_typeof(res) !== \"object\") return res;\n throw new TypeError(\"@@toPrimitive must return a primitive value.\");\n }\n return (hint === \"string\" ? String : Number)(input);\n}","export default function _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nimport isNativeReflectConstruct from \"./isNativeReflectConstruct.js\";\nexport default function _construct(Parent, args, Class) {\n if (isNativeReflectConstruct()) {\n _construct = Reflect.construct.bind();\n } else {\n _construct = function _construct(Parent, args, Class) {\n var a = [null];\n a.push.apply(a, args);\n var Constructor = Function.bind.apply(Parent, a);\n var instance = new Constructor();\n if (Class) setPrototypeOf(instance, Class.prototype);\n return instance;\n };\n }\n return _construct.apply(null, arguments);\n}","import getPrototypeOf from \"./getPrototypeOf.js\";\nimport setPrototypeOf from \"./setPrototypeOf.js\";\nimport isNativeFunction from \"./isNativeFunction.js\";\nimport construct from \"./construct.js\";\nexport default function _wrapNativeSuper(Class) {\n var _cache = typeof Map === \"function\" ? new Map() : undefined;\n _wrapNativeSuper = function _wrapNativeSuper(Class) {\n if (Class === null || !isNativeFunction(Class)) return Class;\n if (typeof Class !== \"function\") {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n if (typeof _cache !== \"undefined\") {\n if (_cache.has(Class)) return _cache.get(Class);\n _cache.set(Class, Wrapper);\n }\n function Wrapper() {\n return construct(Class, arguments, getPrototypeOf(this).constructor);\n }\n Wrapper.prototype = Object.create(Class.prototype, {\n constructor: {\n value: Wrapper,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n return setPrototypeOf(Wrapper, Class);\n };\n return _wrapNativeSuper(Class);\n}","export default function _isNativeFunction(fn) {\n return Function.toString.call(fn).indexOf(\"[native code]\") !== -1;\n}","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"../error/AuthError\";\nimport { NetworkResponse } from \"./NetworkManager\";\n\n/**\n * Options allowed by network request APIs.\n */\nexport type NetworkRequestOptions = {\n headers?: Record;\n body?: string;\n};\n\n/**\n * Client network interface to send backend requests.\n * @interface\n */\nexport interface INetworkModule {\n /**\n * Interface function for async network \"GET\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\n * @param url\n * @param requestParams\n * @param enableCaching\n */\n sendGetRequestAsync(\n url: string,\n options?: NetworkRequestOptions,\n cancellationToken?: number\n ): Promise>;\n\n /**\n * Interface function for async network \"POST\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\n * @param url\n * @param requestParams\n * @param enableCaching\n */\n sendPostRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise>;\n}\n\nexport const StubbedNetworkModule: INetworkModule = {\n sendGetRequestAsync: () => {\n const notImplErr =\n \"Network interface - sendGetRequestAsync() has not been implemented for the Network interface.\";\n return Promise.reject(AuthError.createUnexpectedError(notImplErr));\n },\n sendPostRequestAsync: () => {\n const notImplErr =\n \"Network interface - sendPostRequestAsync() has not been implemented for the Network interface.\";\n return Promise.reject(AuthError.createUnexpectedError(notImplErr));\n },\n};\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IPerformanceClient,\n InProgressPerformanceEvent,\n} from \"./IPerformanceClient\";\nimport { IPerformanceMeasurement } from \"./IPerformanceMeasurement\";\nimport { PerformanceEvent, PerformanceEventStatus } from \"./PerformanceEvent\";\n\nexport class StubPerformanceMeasurement implements IPerformanceMeasurement {\n startMeasurement(): void {\n return;\n }\n endMeasurement(): void {\n return;\n }\n flushMeasurement(): number | null {\n return null;\n }\n}\n\nexport class StubPerformanceClient implements IPerformanceClient {\n generateId(): string {\n return \"callback-id\";\n }\n\n startMeasurement(\n measureName: string,\n correlationId?: string | undefined\n ): InProgressPerformanceEvent {\n return {\n end: () => null,\n discard: () => {},\n add: () => {},\n increment: () => {},\n event: {\n eventId: this.generateId(),\n status: PerformanceEventStatus.InProgress,\n authority: \"\",\n libraryName: \"\",\n libraryVersion: \"\",\n clientId: \"\",\n name: measureName,\n startTimeMs: Date.now(),\n correlationId: correlationId || \"\",\n },\n measurement: new StubPerformanceMeasurement(),\n };\n }\n\n startPerformanceMeasurement(): IPerformanceMeasurement {\n return new StubPerformanceMeasurement();\n }\n\n calculateQueuedTime(): number {\n return 0;\n }\n\n addQueueMeasurement(): void {\n return;\n }\n\n setPreQueueTime(): void {\n return;\n }\n\n endMeasurement(): PerformanceEvent | null {\n return null;\n }\n\n discardMeasurements(): void {\n return;\n }\n\n removePerformanceCallback(): boolean {\n return true;\n }\n\n addPerformanceCallback(): string {\n return \"\";\n }\n\n emitEvents(): void {\n return;\n }\n\n addFields(): void {\n return;\n }\n\n incrementFields(): void {\n return;\n }\n\n cacheEventByCorrelationId(): void {\n return;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { INavigationClient } from \"./INavigationClient\";\nimport { NavigationOptions } from \"./NavigationOptions\";\n\nexport class NavigationClient implements INavigationClient {\n /**\n * Navigates to other pages within the same web application\n * @param url\n * @param options\n */\n navigateInternal(\n url: string,\n options: NavigationOptions\n ): Promise {\n return NavigationClient.defaultNavigateWindow(url, options);\n }\n\n /**\n * Navigates to other pages outside the web application i.e. the Identity Provider\n * @param url\n * @param options\n */\n navigateExternal(\n url: string,\n options: NavigationOptions\n ): Promise {\n return NavigationClient.defaultNavigateWindow(url, options);\n }\n\n /**\n * Default navigation implementation invoked by the internal and external functions\n * @param url\n * @param options\n */\n private static defaultNavigateWindow(\n url: string,\n options: NavigationOptions\n ): Promise {\n if (options.noHistory) {\n window.location.replace(url);\n } else {\n window.location.assign(url);\n }\n\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(true);\n }, options.timeout);\n });\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Constants,\n INetworkModule,\n NetworkRequestOptions,\n NetworkResponse,\n} from \"@azure/msal-common\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { HTTP_REQUEST_TYPE } from \"../utils/BrowserConstants\";\n\n/**\n * This class implements the Fetch API for GET and POST requests. See more here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n */\nexport class FetchClient implements INetworkModule {\n /**\n * Fetch Client for REST endpoints - Get request\n * @param url\n * @param headers\n * @param body\n */\n async sendGetRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise> {\n let response;\n try {\n response = await fetch(url, {\n method: HTTP_REQUEST_TYPE.GET,\n headers: this.getFetchHeaders(options),\n });\n } catch (e) {\n if (window.navigator.onLine) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.getRequestFailed\n );\n } else {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.noNetworkConnectivity\n );\n }\n }\n\n try {\n return {\n headers: this.getHeaderDict(response.headers),\n body: (await response.json()) as T,\n status: response.status,\n };\n } catch (e) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToParseResponse\n );\n }\n }\n\n /**\n * Fetch Client for REST endpoints - Post request\n * @param url\n * @param headers\n * @param body\n */\n async sendPostRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise> {\n const reqBody = (options && options.body) || Constants.EMPTY_STRING;\n\n let response;\n try {\n response = await fetch(url, {\n method: HTTP_REQUEST_TYPE.POST,\n headers: this.getFetchHeaders(options),\n body: reqBody,\n });\n } catch (e) {\n if (window.navigator.onLine) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.postRequestFailed\n );\n } else {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.noNetworkConnectivity\n );\n }\n }\n\n try {\n return {\n headers: this.getHeaderDict(response.headers),\n body: (await response.json()) as T,\n status: response.status,\n };\n } catch (e) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToParseResponse\n );\n }\n }\n\n /**\n * Get Fetch API Headers object from string map\n * @param inputHeaders\n */\n private getFetchHeaders(options?: NetworkRequestOptions): Headers {\n const headers = new Headers();\n if (!(options && options.headers)) {\n return headers;\n }\n const optionsHeaders = options.headers;\n Object.keys(optionsHeaders).forEach((key) => {\n headers.append(key, optionsHeaders[key]);\n });\n return headers;\n }\n\n private getHeaderDict(headers: Headers): Record {\n const headerDict: Record = {};\n headers.forEach((value: string, key: string) => {\n headerDict[key] = value;\n });\n return headerDict;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n SystemOptions,\n LoggerOptions,\n INetworkModule,\n DEFAULT_SYSTEM_OPTIONS,\n Constants,\n ProtocolMode,\n OIDCOptions,\n ServerResponseType,\n LogLevel,\n StubbedNetworkModule,\n AzureCloudInstance,\n AzureCloudOptions,\n ApplicationTelemetry,\n ClientConfigurationError,\n IPerformanceClient,\n StubPerformanceClient,\n} from \"@azure/msal-common\";\nimport {\n BrowserCacheLocation,\n BrowserConstants,\n} from \"../utils/BrowserConstants\";\nimport { INavigationClient } from \"../navigation/INavigationClient\";\nimport { NavigationClient } from \"../navigation/NavigationClient\";\nimport { FetchClient } from \"../network/FetchClient\";\n\n// Default timeout for popup windows and iframes in milliseconds\nexport const DEFAULT_POPUP_TIMEOUT_MS = 60000;\nexport const DEFAULT_IFRAME_TIMEOUT_MS = 6000;\nexport const DEFAULT_REDIRECT_TIMEOUT_MS = 30000;\nexport const DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS = 2000;\n\n/**\n * Use this to configure the auth options in the Configuration object\n */\nexport type BrowserAuthOptions = {\n /**\n * Client ID of your app registered with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview in Microsoft Identity Platform\n */\n clientId: string;\n /**\n * You can configure a specific authority, defaults to \" \" or \"https://login.microsoftonline.com/common\"\n */\n authority?: string;\n /**\n * An array of URIs that are known to be valid. Used in B2C scenarios.\n */\n knownAuthorities?: Array;\n /**\n * A string containing the cloud discovery response. Used in AAD scenarios.\n */\n cloudDiscoveryMetadata?: string;\n /**\n * A string containing the .well-known/openid-configuration endpoint response\n */\n authorityMetadata?: string;\n /**\n * The redirect URI where authentication responses can be received by your application. It must exactly match one of the redirect URIs registered in the Azure portal.\n */\n redirectUri?: string;\n /**\n * The redirect URI where the window navigates after a successful logout.\n */\n postLogoutRedirectUri?: string | null;\n /**\n * Boolean indicating whether to navigate to the original request URL after the auth server navigates to the redirect URL.\n */\n navigateToLoginRequestUrl?: boolean;\n /**\n * Array of capabilities which will be added to the claims.access_token.xms_cc request property on every network request.\n */\n clientCapabilities?: Array;\n /**\n * Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\n */\n protocolMode?: ProtocolMode;\n /**\n * Enum that configures options for the OIDC protocol mode.\n */\n OIDCOptions?: OIDCOptions;\n /**\n * Enum that represents the Azure Cloud to use.\n */\n azureCloudOptions?: AzureCloudOptions;\n /**\n * Flag of whether to use the local metadata cache\n */\n skipAuthorityMetadataCache?: boolean;\n};\n\n/** @internal */\nexport type InternalAuthOptions = Required & {\n OIDCOptions: Required;\n};\n\n/**\n * Use this to configure the below cache configuration options:\n */\nexport type CacheOptions = {\n /**\n * Used to specify the cacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\n */\n cacheLocation?: BrowserCacheLocation | string;\n /**\n * Used to specify the temporaryCacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\n */\n temporaryCacheLocation?: BrowserCacheLocation | string;\n /**\n * If set, MSAL stores the auth request state required for validation of the auth flows in the browser cookies. By default this flag is set to false.\n */\n storeAuthStateInCookie?: boolean;\n /**\n * If set, MSAL sets the \"Secure\" flag on cookies so they can only be sent over HTTPS. By default this flag is set to false.\n */\n secureCookies?: boolean;\n /**\n * If set, MSAL will attempt to migrate cache entries from older versions on initialization. By default this flag is set to true if cacheLocation is localStorage, otherwise false.\n */\n cacheMigrationEnabled?: boolean;\n /**\n * Flag that determines whether access tokens are stored based on requested claims\n */\n claimsBasedCachingEnabled?: boolean;\n};\n\nexport type BrowserSystemOptions = SystemOptions & {\n /**\n * Used to initialize the Logger object (See ClientConfiguration.ts)\n */\n loggerOptions?: LoggerOptions;\n /**\n * Network interface implementation\n */\n networkClient?: INetworkModule;\n /**\n * Override the methods used to navigate to other webpages. Particularly useful if you are using a client-side router\n */\n navigationClient?: INavigationClient;\n /**\n * Sets the timeout for waiting for a response hash in a popup. Will take precedence over loadFrameTimeout if both are set.\n */\n windowHashTimeout?: number;\n /**\n * Sets the timeout for waiting for a response hash in an iframe. Will take precedence over loadFrameTimeout if both are set.\n */\n iframeHashTimeout?: number;\n /**\n * Sets the timeout for waiting for a response hash in an iframe or popup\n */\n loadFrameTimeout?: number;\n /**\n * Maximum time the library should wait for a frame to load\n * @deprecated This was previously needed for older browsers which are no longer supported by MSAL.js. This option will be removed in the next major version\n */\n navigateFrameWait?: number;\n /**\n * Time to wait for redirection to occur before resolving promise\n */\n redirectNavigationTimeout?: number;\n /**\n * Sets whether popups are opened asynchronously. By default, this flag is set to false. When set to false, blank popups are opened before anything else happens. When set to true, popups are opened when making the network request.\n */\n asyncPopups?: boolean;\n /**\n * Flag to enable redirect opertaions when the app is rendered in an iframe (to support scenarios such as embedded B2C login).\n */\n allowRedirectInIframe?: boolean;\n /**\n * Flag to enable native broker support (e.g. acquiring tokens from WAM on Windows)\n */\n allowNativeBroker?: boolean;\n /**\n * Sets the timeout for waiting for the native broker handshake to resolve\n */\n nativeBrokerHandshakeTimeout?: number;\n /**\n * Sets the interval length in milliseconds for polling the location attribute in popup windows (default is 30ms)\n */\n pollIntervalMilliseconds?: number;\n};\n\n/**\n * Telemetry Options\n */\nexport type BrowserTelemetryOptions = {\n /**\n * Telemetry information sent on request\n * - appName: Unique string name of an application\n * - appVersion: Version of the application using MSAL\n */\n application?: ApplicationTelemetry;\n\n client?: IPerformanceClient;\n};\n\n/**\n * This object allows you to configure important elements of MSAL functionality and is passed into the constructor of PublicClientApplication\n */\nexport type Configuration = {\n /**\n * This is where you configure auth elements like clientID, authority used for authenticating against the Microsoft Identity Platform\n */\n auth: BrowserAuthOptions;\n /**\n * This is where you configure cache location and whether to store cache in cookies\n */\n cache?: CacheOptions;\n /**\n * This is where you can configure the network client, logger, token renewal offset\n */\n system?: BrowserSystemOptions;\n /**\n * This is where you can configure telemetry data and options\n */\n telemetry?: BrowserTelemetryOptions;\n};\n\n/** @internal */\nexport type BrowserConfiguration = {\n auth: InternalAuthOptions;\n cache: Required;\n system: Required;\n telemetry: Required;\n};\n\n/**\n * MSAL function that sets the default options when not explicitly configured from app developer\n *\n * @param auth\n * @param cache\n * @param system\n *\n * @returns Configuration object\n */\nexport function buildConfiguration(\n {\n auth: userInputAuth,\n cache: userInputCache,\n system: userInputSystem,\n telemetry: userInputTelemetry,\n }: Configuration,\n isBrowserEnvironment: boolean\n): BrowserConfiguration {\n // Default auth options for browser\n const DEFAULT_AUTH_OPTIONS: InternalAuthOptions = {\n clientId: Constants.EMPTY_STRING,\n authority: `${Constants.DEFAULT_AUTHORITY}`,\n knownAuthorities: [],\n cloudDiscoveryMetadata: Constants.EMPTY_STRING,\n authorityMetadata: Constants.EMPTY_STRING,\n redirectUri: Constants.EMPTY_STRING,\n postLogoutRedirectUri: Constants.EMPTY_STRING,\n navigateToLoginRequestUrl: true,\n clientCapabilities: [],\n protocolMode: ProtocolMode.AAD,\n OIDCOptions: {\n serverResponseType: ServerResponseType.FRAGMENT,\n defaultScopes: [\n Constants.OPENID_SCOPE,\n Constants.PROFILE_SCOPE,\n Constants.OFFLINE_ACCESS_SCOPE,\n ],\n },\n azureCloudOptions: {\n azureCloudInstance: AzureCloudInstance.None,\n tenant: Constants.EMPTY_STRING,\n },\n skipAuthorityMetadataCache: false,\n };\n\n // Default cache options for browser\n const DEFAULT_CACHE_OPTIONS: Required = {\n cacheLocation: BrowserCacheLocation.SessionStorage,\n temporaryCacheLocation: BrowserCacheLocation.SessionStorage,\n storeAuthStateInCookie: false,\n secureCookies: false,\n // Default cache migration to true if cache location is localStorage since entries are preserved across tabs/windows. Migration has little to no benefit in sessionStorage and memoryStorage\n cacheMigrationEnabled:\n userInputCache &&\n userInputCache.cacheLocation === BrowserCacheLocation.LocalStorage\n ? true\n : false,\n claimsBasedCachingEnabled: false,\n };\n\n // Default logger options for browser\n const DEFAULT_LOGGER_OPTIONS: LoggerOptions = {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n loggerCallback: (): void => {\n // allow users to not set logger call back\n },\n logLevel: LogLevel.Info,\n piiLoggingEnabled: false,\n };\n\n // Default system options for browser\n const DEFAULT_BROWSER_SYSTEM_OPTIONS: Required = {\n ...DEFAULT_SYSTEM_OPTIONS,\n loggerOptions: DEFAULT_LOGGER_OPTIONS,\n networkClient: isBrowserEnvironment\n ? new FetchClient()\n : StubbedNetworkModule,\n navigationClient: new NavigationClient(),\n loadFrameTimeout: 0,\n // If loadFrameTimeout is provided, use that as default.\n windowHashTimeout:\n userInputSystem?.loadFrameTimeout || DEFAULT_POPUP_TIMEOUT_MS,\n iframeHashTimeout:\n userInputSystem?.loadFrameTimeout || DEFAULT_IFRAME_TIMEOUT_MS,\n navigateFrameWait: 0,\n redirectNavigationTimeout: DEFAULT_REDIRECT_TIMEOUT_MS,\n asyncPopups: false,\n allowRedirectInIframe: false,\n allowNativeBroker: false,\n nativeBrokerHandshakeTimeout:\n userInputSystem?.nativeBrokerHandshakeTimeout ||\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\n pollIntervalMilliseconds: BrowserConstants.DEFAULT_POLL_INTERVAL_MS,\n };\n\n const providedSystemOptions: BrowserSystemOptions = {\n ...userInputSystem,\n loggerOptions: userInputSystem?.loggerOptions || DEFAULT_LOGGER_OPTIONS,\n };\n\n const DEFAULT_TELEMETRY_OPTIONS: Required = {\n application: {\n appName: Constants.EMPTY_STRING,\n appVersion: Constants.EMPTY_STRING,\n },\n client: new StubPerformanceClient(),\n };\n\n // Throw an error if user has set OIDCOptions without being in OIDC protocol mode\n if (\n userInputAuth?.protocolMode !== ProtocolMode.OIDC &&\n userInputAuth?.OIDCOptions\n ) {\n // Logger has not been created yet\n // eslint-disable-next-line no-console\n console.warn(\n ClientConfigurationError.createCannotSetOIDCOptionsError()\n );\n }\n\n // Throw an error if user has set allowNativeBroker to true without being in AAD protocol mode\n if (\n userInputAuth?.protocolMode &&\n userInputAuth.protocolMode !== ProtocolMode.AAD &&\n providedSystemOptions?.allowNativeBroker\n ) {\n throw ClientConfigurationError.createCannotAllowNativeBrokerError();\n }\n\n const overlayedConfig: BrowserConfiguration = {\n auth: {\n ...DEFAULT_AUTH_OPTIONS,\n ...userInputAuth,\n OIDCOptions: {\n ...DEFAULT_AUTH_OPTIONS.OIDCOptions,\n ...userInputAuth?.OIDCOptions,\n },\n },\n cache: { ...DEFAULT_CACHE_OPTIONS, ...userInputCache },\n system: { ...DEFAULT_BROWSER_SYSTEM_OPTIONS, ...providedSystemOptions },\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...userInputTelemetry },\n };\n\n return overlayedConfig;\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError\";\n\n/**\n * ClientAuthErrorMessage class containing string constants used by error codes and messages.\n */\nexport const JoseHeaderErrorMessage = {\n missingKidError: {\n code: \"missing_kid_error\",\n desc: \"The JOSE Header for the requested JWT, JWS or JWK object requires a keyId to be configured as the 'kid' header claim. No 'kid' value was provided.\",\n },\n missingAlgError: {\n code: \"missing_alg_error\",\n desc: \"The JOSE Header for the requested JWT, JWS or JWK object requires an algorithm to be specified as the 'alg' header claim. No 'alg' value was provided.\",\n },\n};\n\n/**\n * Error thrown when there is an error in the client code running on the browser.\n */\nexport class JoseHeaderError extends AuthError {\n constructor(errorCode: string, errorMessage?: string) {\n super(errorCode, errorMessage);\n this.name = \"JoseHeaderError\";\n\n Object.setPrototypeOf(this, JoseHeaderError.prototype);\n }\n\n /**\n * Creates an error thrown when keyId isn't set on JOSE header.\n */\n static createMissingKidError(): JoseHeaderError {\n return new JoseHeaderError(\n JoseHeaderErrorMessage.missingKidError.code,\n JoseHeaderErrorMessage.missingKidError.desc\n );\n }\n\n /**\n * Creates an error thrown when algorithm isn't set on JOSE header.\n */\n static createMissingAlgError(): JoseHeaderError {\n return new JoseHeaderError(\n JoseHeaderErrorMessage.missingAlgError.code,\n JoseHeaderErrorMessage.missingAlgError.desc\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { JoseHeaderError } from \"../error/JoseHeaderError\";\nimport { JsonTypes } from \"../utils/Constants\";\n\nexport type JoseHeaderOptions = {\n typ?: JsonTypes;\n alg?: string;\n kid?: string;\n};\n\n/** @internal */\nexport class JoseHeader {\n public typ?: JsonTypes;\n public alg?: string;\n public kid?: string;\n\n constructor(options: JoseHeaderOptions) {\n this.typ = options.typ;\n this.alg = options.alg;\n this.kid = options.kid;\n }\n\n /**\n * Builds SignedHttpRequest formatted JOSE Header from the\n * JOSE Header options provided or previously set on the object and returns\n * the stringified header object.\n * Throws if keyId or algorithm aren't provided since they are required for Access Token Binding.\n * @param shrHeaderOptions\n * @returns\n */\n static getShrHeaderString(shrHeaderOptions: JoseHeaderOptions): string {\n // KeyID is required on the SHR header\n if (!shrHeaderOptions.kid) {\n throw JoseHeaderError.createMissingKidError();\n }\n\n // Alg is required on the SHR header\n if (!shrHeaderOptions.alg) {\n throw JoseHeaderError.createMissingAlgError();\n }\n\n const shrHeader = new JoseHeader({\n // Access Token PoP headers must have type pop, but the type header can be overriden for special cases\n typ: shrHeaderOptions.typ || JsonTypes.Pop,\n kid: shrHeaderOptions.kid,\n alg: shrHeaderOptions.alg,\n });\n\n return JSON.stringify(shrHeader);\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Class which exposes APIs to encode plaintext to base64 encoded string. See here for implementation details:\n * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_JavaScript's_UTF-16_%3E_UTF-8_%3E_base64\n */\n\n/**\n * Returns URL Safe b64 encoded string from a plaintext string.\n * @param input\n */\nexport function urlEncode(input: string): string {\n return encodeURIComponent(\n base64Encode(input)\n .replace(/=/g, \"\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n );\n}\n\n/**\n * Returns URL Safe b64 encoded string from an int8Array.\n * @param inputArr\n */\nexport function urlEncodeArr(inputArr: Uint8Array): string {\n return base64EncArr(inputArr)\n .replace(/=/g, \"\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\");\n}\n\n/**\n * Returns b64 encoded string from plaintext string.\n * @param input\n */\nexport function base64Encode(input: string): string {\n return base64EncArr(new TextEncoder().encode(input));\n}\n\n/**\n * Base64 encode byte array\n * @param aBytes\n */\nfunction base64EncArr(aBytes: Uint8Array): string {\n const binString = Array.from(aBytes, (x) => String.fromCodePoint(x)).join(\n \"\"\n );\n return btoa(binString);\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { PkceCodes } from \"@azure/msal-common\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { urlEncodeArr } from \"../encode/Base64Encode\";\nimport { BrowserCrypto } from \"./BrowserCrypto\";\n\n// Constant byte array length\nconst RANDOM_BYTE_ARR_LENGTH = 32;\n\n/**\n * Class which exposes APIs to generate PKCE codes and code verifiers.\n */\nexport class PkceGenerator {\n private cryptoObj: BrowserCrypto;\n\n constructor(cryptoObj: BrowserCrypto) {\n this.cryptoObj = cryptoObj;\n }\n\n /**\n * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636\n */\n async generateCodes(): Promise {\n const codeVerifier = this.generateCodeVerifier();\n const codeChallenge = await this.generateCodeChallengeFromVerifier(\n codeVerifier\n );\n return {\n verifier: codeVerifier,\n challenge: codeChallenge,\n };\n }\n\n /**\n * Generates a random 32 byte buffer and returns the base64\n * encoded string to be used as a PKCE Code Verifier\n */\n private generateCodeVerifier(): string {\n try {\n // Generate random values as utf-8\n const buffer: Uint8Array = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);\n this.cryptoObj.getRandomValues(buffer);\n // encode verifier as base64\n const pkceCodeVerifierB64: string = urlEncodeArr(buffer);\n return pkceCodeVerifierB64;\n } catch (e) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\n }\n }\n\n /**\n * Creates a base64 encoded PKCE Code Challenge string from the\n * hash created from the PKCE Code Verifier supplied\n */\n private async generateCodeChallengeFromVerifier(\n pkceCodeVerifier: string\n ): Promise {\n try {\n // hashed verifier\n const pkceHashedCodeVerifier = await this.cryptoObj.sha256Digest(\n pkceCodeVerifier\n );\n // encode hash as base64\n return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));\n } catch (e) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants } from \"@azure/msal-common\";\n\n/**\n * Utility functions for strings in a browser. See here for implementation details:\n * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_JavaScript's_UTF-16_%3E_UTF-8_%3E_base64\n */\nexport class BrowserStringUtils {\n /**\n * Converts string to Uint8Array\n * @param sDOMStr\n */\n static stringToUtf8Arr(sDOMStr: string): Uint8Array {\n let nChr;\n let nArrLen = 0;\n const nStrLen = sDOMStr.length;\n /* mapping... */\n for (let nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {\n nChr = sDOMStr.charCodeAt(nMapIdx);\n nArrLen +=\n nChr < 0x80\n ? 1\n : nChr < 0x800\n ? 2\n : nChr < 0x10000\n ? 3\n : nChr < 0x200000\n ? 4\n : nChr < 0x4000000\n ? 5\n : 6;\n }\n\n const aBytes = new Uint8Array(nArrLen);\n\n /* transcription... */\n\n for (let nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) {\n nChr = sDOMStr.charCodeAt(nChrIdx);\n if (nChr < 128) {\n /* one byte */\n aBytes[nIdx++] = nChr;\n } else if (nChr < 0x800) {\n /* two bytes */\n aBytes[nIdx++] = 192 + (nChr >>> 6);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } else if (nChr < 0x10000) {\n /* three bytes */\n aBytes[nIdx++] = 224 + (nChr >>> 12);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } else if (nChr < 0x200000) {\n /* four bytes */\n aBytes[nIdx++] = 240 + (nChr >>> 18);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } else if (nChr < 0x4000000) {\n /* five bytes */\n aBytes[nIdx++] = 248 + (nChr >>> 24);\n aBytes[nIdx++] = 128 + ((nChr >>> 18) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } /* if (nChr <= 0x7fffffff) */ else {\n /* six bytes */\n aBytes[nIdx++] = 252 + (nChr >>> 30);\n aBytes[nIdx++] = 128 + ((nChr >>> 24) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 18) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n }\n }\n\n return aBytes;\n }\n\n /**\n * Converts Uint8Array to a string\n * @param aBytes\n */\n static utf8ArrToString(aBytes: Uint8Array): string {\n let sView = Constants.EMPTY_STRING;\n for (let nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {\n nPart = aBytes[nIdx];\n sView += String.fromCharCode(\n nPart > 251 && nPart < 254 && nIdx + 5 < nLen /* six bytes */\n ? /* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */\n (nPart - 252) * 1073741824 +\n ((aBytes[++nIdx] - 128) << 24) +\n ((aBytes[++nIdx] - 128) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 247 &&\n nPart < 252 &&\n nIdx + 4 < nLen /* five bytes */\n ? ((nPart - 248) << 24) +\n ((aBytes[++nIdx] - 128) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 239 &&\n nPart < 248 &&\n nIdx + 3 < nLen /* four bytes */\n ? ((nPart - 240) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 223 &&\n nPart < 240 &&\n nIdx + 2 < nLen /* three bytes */\n ? ((nPart - 224) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 191 &&\n nPart < 224 &&\n nIdx + 1 < nLen /* two bytes */\n ? ((nPart - 192) << 6) + aBytes[++nIdx] - 128\n : /* nPart < 127 ? */ /* one byte */\n nPart\n );\n }\n return sView;\n }\n\n /**\n * Returns stringified jwk.\n * @param jwk\n */\n static getSortedObjectString(obj: object): string {\n return JSON.stringify(obj, Object.keys(obj).sort());\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { KEY_FORMAT_JWK } from \"../utils/BrowserConstants\";\nimport { ISubtleCrypto } from \"./ISubtleCrypto\";\n\nexport class ModernBrowserCrypto implements ISubtleCrypto {\n getRandomValues(dataBuffer: Uint8Array): Uint8Array {\n return window.crypto.getRandomValues(dataBuffer);\n }\n\n async generateKey(\n algorithm: RsaHashedKeyGenParams,\n extractable: boolean,\n keyUsages: KeyUsage[]\n ): Promise {\n return window.crypto.subtle.generateKey(\n algorithm,\n extractable,\n keyUsages\n ) as Promise;\n }\n\n async exportKey(key: CryptoKey): Promise {\n return window.crypto.subtle.exportKey(\n KEY_FORMAT_JWK,\n key\n ) as Promise;\n }\n\n async importKey(\n keyData: JsonWebKey,\n algorithm: RsaHashedImportParams,\n extractable: boolean,\n keyUsages: KeyUsage[]\n ): Promise {\n return window.crypto.subtle.importKey(\n KEY_FORMAT_JWK,\n keyData,\n algorithm,\n extractable,\n keyUsages\n ) as Promise;\n }\n\n async sign(\n algorithm: AlgorithmIdentifier,\n key: CryptoKey,\n data: ArrayBuffer\n ): Promise {\n return window.crypto.subtle.sign(\n algorithm,\n key,\n data\n ) as Promise;\n }\n\n async digest(\n algorithm: AlgorithmIdentifier,\n data: Uint8Array\n ): Promise {\n return window.crypto.subtle.digest(\n algorithm,\n data\n ) as Promise;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BrowserStringUtils } from \"../utils/BrowserStringUtils\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { ISubtleCrypto } from \"./ISubtleCrypto\";\nimport { ModernBrowserCrypto } from \"./ModernBrowserCrypto\";\nimport { Logger } from \"@azure/msal-common\";\n/**\n * See here for more info on RsaHashedKeyGenParams: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams\n */\n// RSA KeyGen Algorithm\nconst PKCS1_V15_KEYGEN_ALG = \"RSASSA-PKCS1-v1_5\";\n// SHA-256 hashing algorithm\nconst S256_HASH_ALG = \"SHA-256\";\n// MOD length for PoP tokens\nconst MODULUS_LENGTH = 2048;\n// Public Exponent\nconst PUBLIC_EXPONENT: Uint8Array = new Uint8Array([0x01, 0x00, 0x01]);\n\n/**\n * This class implements functions used by the browser library to perform cryptography operations such as\n * hashing and encoding. It also has helper functions to validate the availability of specific APIs.\n */\nexport class BrowserCrypto {\n private keygenAlgorithmOptions: RsaHashedKeyGenParams;\n private subtleCrypto: ISubtleCrypto;\n private logger: Logger;\n\n constructor(logger: Logger) {\n this.logger = logger;\n\n if (this.hasBrowserCrypto()) {\n // Use standard modern web crypto if available\n this.logger.verbose(\n \"BrowserCrypto: modern crypto interface available\"\n );\n this.subtleCrypto = new ModernBrowserCrypto();\n } else {\n this.logger.error(\"BrowserCrypto: crypto interface is unavailable\");\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.cryptoNonExistent\n );\n }\n\n this.keygenAlgorithmOptions = {\n name: PKCS1_V15_KEYGEN_ALG,\n hash: S256_HASH_ALG,\n modulusLength: MODULUS_LENGTH,\n publicExponent: PUBLIC_EXPONENT,\n };\n }\n\n /**\n * Check whether browser crypto is available.\n */\n private hasBrowserCrypto(): boolean {\n return \"crypto\" in window;\n }\n\n /**\n * Returns a sha-256 hash of the given dataString as an ArrayBuffer.\n * @param dataString\n */\n async sha256Digest(dataString: string): Promise {\n const data = BrowserStringUtils.stringToUtf8Arr(dataString);\n // MSR Crypto wants object with name property, instead of string\n return this.subtleCrypto.digest({ name: S256_HASH_ALG }, data);\n }\n\n /**\n * Populates buffer with cryptographically random values.\n * @param dataBuffer\n */\n getRandomValues(dataBuffer: Uint8Array): Uint8Array {\n return this.subtleCrypto.getRandomValues(dataBuffer);\n }\n\n /**\n * Generates a keypair based on current keygen algorithm config.\n * @param extractable\n * @param usages\n */\n async generateKeyPair(\n extractable: boolean,\n usages: Array\n ): Promise {\n return this.subtleCrypto.generateKey(\n this.keygenAlgorithmOptions,\n extractable,\n usages\n );\n }\n\n /**\n * Export key as Json Web Key (JWK)\n * @param key\n */\n async exportJwk(key: CryptoKey): Promise {\n return this.subtleCrypto.exportKey(key);\n }\n\n /**\n * Imports key as Json Web Key (JWK), can set extractable and usages.\n * @param key\n * @param extractable\n * @param usages\n */\n async importJwk(\n key: JsonWebKey,\n extractable: boolean,\n usages: Array\n ): Promise {\n return this.subtleCrypto.importKey(\n key,\n this.keygenAlgorithmOptions,\n extractable,\n usages\n );\n }\n\n /**\n * Signs given data with given key\n * @param key\n * @param data\n */\n async sign(key: CryptoKey, data: ArrayBuffer): Promise {\n return this.subtleCrypto.sign(this.keygenAlgorithmOptions, key, data);\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { DB_NAME, DB_TABLE_NAME, DB_VERSION } from \"../utils/BrowserConstants\";\nimport { IAsyncStorage } from \"./IAsyncMemoryStorage\";\n\ninterface IDBOpenDBRequestEvent extends Event {\n target: IDBOpenDBRequest & EventTarget;\n}\n\ninterface IDBOpenOnUpgradeNeededEvent extends IDBVersionChangeEvent {\n target: IDBOpenDBRequest & EventTarget;\n}\n\ninterface IDBRequestEvent extends Event {\n target: IDBRequest & EventTarget;\n}\n\n/**\n * Storage wrapper for IndexedDB storage in browsers: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n */\nexport class DatabaseStorage implements IAsyncStorage {\n private db: IDBDatabase | undefined;\n private dbName: string;\n private tableName: string;\n private version: number;\n private dbOpen: boolean;\n\n constructor() {\n this.dbName = DB_NAME;\n this.version = DB_VERSION;\n this.tableName = DB_TABLE_NAME;\n this.dbOpen = false;\n }\n\n /**\n * Opens IndexedDB instance.\n */\n async open(): Promise {\n return new Promise((resolve, reject) => {\n const openDB = window.indexedDB.open(this.dbName, this.version);\n openDB.addEventListener(\n \"upgradeneeded\",\n (e: IDBVersionChangeEvent) => {\n const event = e as IDBOpenOnUpgradeNeededEvent;\n event.target.result.createObjectStore(this.tableName);\n }\n );\n openDB.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBOpenDBRequestEvent;\n this.db = event.target.result;\n this.dbOpen = true;\n resolve();\n });\n openDB.addEventListener(\"error\", () =>\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseUnavailable\n )\n )\n );\n });\n }\n\n /**\n * Closes the connection to IndexedDB database when all pending transactions\n * complete.\n */\n closeConnection(): void {\n const db = this.db;\n if (db && this.dbOpen) {\n db.close();\n this.dbOpen = false;\n }\n }\n\n /**\n * Opens database if it's not already open\n */\n private async validateDbIsOpen(): Promise {\n if (!this.dbOpen) {\n return await this.open();\n }\n }\n\n /**\n * Retrieves item from IndexedDB instance.\n * @param key\n */\n async getItem(key: string): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve, reject) => {\n // TODO: Add timeouts?\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbGet = objectStore.get(key);\n\n dbGet.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result);\n });\n\n dbGet.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Adds item to IndexedDB under given key\n * @param key\n * @param payload\n */\n async setItem(key: string, payload: T): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n // TODO: Add timeouts?\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n const transaction = this.db.transaction(\n [this.tableName],\n \"readwrite\"\n );\n\n const objectStore = transaction.objectStore(this.tableName);\n\n const dbPut = objectStore.put(payload, key);\n\n dbPut.addEventListener(\"success\", () => {\n this.closeConnection();\n resolve();\n });\n\n dbPut.addEventListener(\"error\", (e) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Removes item from IndexedDB under given key\n * @param key\n */\n async removeItem(key: string): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readwrite\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbDelete = objectStore.delete(key);\n\n dbDelete.addEventListener(\"success\", () => {\n this.closeConnection();\n resolve();\n });\n\n dbDelete.addEventListener(\"error\", (e) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Get all the keys from the storage object as an iterable array of strings.\n */\n async getKeys(): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbGetKeys = objectStore.getAllKeys();\n\n dbGetKeys.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result);\n });\n\n dbGetKeys.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n *\n * Checks whether there is an object under the search key in the object store\n */\n async containsKey(key: string): Promise {\n await this.validateDbIsOpen();\n\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbContainsKey = objectStore.count(key);\n\n dbContainsKey.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result === 1);\n });\n\n dbContainsKey.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Deletes the MSAL database. The database is deleted rather than cleared to make it possible\n * for client applications to downgrade to a previous MSAL version without worrying about forward compatibility issues\n * with IndexedDB database versions.\n */\n async deleteDatabase(): Promise {\n // Check if database being deleted exists\n\n if (this.db && this.dbOpen) {\n this.closeConnection();\n }\n\n return new Promise((resolve: Function, reject: Function) => {\n const deleteDbRequest = window.indexedDB.deleteDatabase(DB_NAME);\n deleteDbRequest.addEventListener(\"success\", () => resolve(true));\n deleteDbRequest.addEventListener(\"blocked\", () => resolve(true));\n deleteDbRequest.addEventListener(\"error\", () => reject(false));\n });\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IWindowStorage } from \"./IWindowStorage\";\n\nexport class MemoryStorage implements IWindowStorage {\n private cache: Map;\n\n constructor() {\n this.cache = new Map();\n }\n\n getItem(key: string): T | null {\n return this.cache.get(key) || null;\n }\n\n setItem(key: string, value: T): void {\n this.cache.set(key, value);\n }\n\n removeItem(key: string): void {\n this.cache.delete(key);\n }\n\n getKeys(): string[] {\n const cacheKeys: string[] = [];\n this.cache.forEach((value: T, key: string) => {\n cacheKeys.push(key);\n });\n return cacheKeys;\n }\n\n containsKey(key: string): boolean {\n return this.cache.has(key);\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common\";\nimport {\n BrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { DatabaseStorage } from \"./DatabaseStorage\";\nimport { IAsyncStorage } from \"./IAsyncMemoryStorage\";\nimport { MemoryStorage } from \"./MemoryStorage\";\n\n/**\n * This class allows MSAL to store artifacts asynchronously using the DatabaseStorage IndexedDB wrapper,\n * backed up with the more volatile MemoryStorage object for cases in which IndexedDB may be unavailable.\n */\nexport class AsyncMemoryStorage implements IAsyncStorage {\n private inMemoryCache: MemoryStorage;\n private indexedDBCache: DatabaseStorage;\n private logger: Logger;\n private storeName: string;\n\n constructor(logger: Logger, storeName: string) {\n this.inMemoryCache = new MemoryStorage();\n this.indexedDBCache = new DatabaseStorage();\n this.logger = logger;\n this.storeName = storeName;\n }\n\n private handleDatabaseAccessError(error: unknown): void {\n if (\n error instanceof BrowserAuthError &&\n error.errorCode === BrowserAuthErrorCodes.databaseUnavailable\n ) {\n this.logger.error(\n \"Could not access persistent storage. This may be caused by browser privacy features which block persistent storage in third-party contexts.\"\n );\n } else {\n throw error;\n }\n }\n /**\n * Get the item matching the given key. Tries in-memory cache first, then in the asynchronous\n * storage object if item isn't found in-memory.\n * @param key\n */\n async getItem(key: string): Promise {\n const item = this.inMemoryCache.getItem(key);\n if (!item) {\n try {\n this.logger.verbose(\n \"Queried item not found in in-memory cache, now querying persistent storage.\"\n );\n return await this.indexedDBCache.getItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return item;\n }\n\n /**\n * Sets the item in the in-memory cache and then tries to set it in the asynchronous\n * storage object with the given key.\n * @param key\n * @param value\n */\n async setItem(key: string, value: T): Promise {\n this.inMemoryCache.setItem(key, value);\n try {\n await this.indexedDBCache.setItem(key, value);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Removes the item matching the key from the in-memory cache, then tries to remove it from the asynchronous storage object.\n * @param key\n */\n async removeItem(key: string): Promise {\n this.inMemoryCache.removeItem(key);\n try {\n await this.indexedDBCache.removeItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Get all the keys from the in-memory cache as an iterable array of strings. If no keys are found, query the keys in the\n * asynchronous storage object.\n */\n async getKeys(): Promise {\n const cacheKeys = this.inMemoryCache.getKeys();\n if (cacheKeys.length === 0) {\n try {\n this.logger.verbose(\n \"In-memory cache is empty, now querying persistent storage.\"\n );\n return await this.indexedDBCache.getKeys();\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return cacheKeys;\n }\n\n /**\n * Returns true or false if the given key is present in the cache.\n * @param key\n */\n async containsKey(key: string): Promise {\n const containsKey = this.inMemoryCache.containsKey(key);\n if (!containsKey) {\n try {\n this.logger.verbose(\n \"Key not found in in-memory cache, now querying persistent storage.\"\n );\n return await this.indexedDBCache.containsKey(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return containsKey;\n }\n\n /**\n * Clears in-memory Map\n */\n clearInMemory(): void {\n // InMemory cache is a Map instance, clear is straightforward\n this.logger.verbose(`Deleting in-memory keystore ${this.storeName}`);\n this.inMemoryCache.clear();\n this.logger.verbose(`In-memory keystore ${this.storeName} deleted`);\n }\n\n /**\n * Tries to delete the IndexedDB database\n * @returns\n */\n async clearPersistent(): Promise {\n try {\n this.logger.verbose(\"Deleting persistent keystore\");\n const dbDeleted = await this.indexedDBCache.deleteDatabase();\n if (dbDeleted) {\n this.logger.verbose(\"Persistent keystore deleted\");\n }\n\n return dbDeleted;\n } catch (e) {\n this.handleDatabaseAccessError(e);\n return false;\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common\";\nimport { CachedKeyPair } from \"../crypto/CryptoOps\";\nimport { AsyncMemoryStorage } from \"./AsyncMemoryStorage\";\n\nexport const CryptoKeyStoreNames = {\n asymmetricKeys: \"asymmetricKeys\",\n symmetricKeys: \"symmetricKeys\",\n} as const;\nexport type CryptoKeyStoreNames =\n (typeof CryptoKeyStoreNames)[keyof typeof CryptoKeyStoreNames];\n\n/**\n * MSAL CryptoKeyStore DB Version 2\n */\nexport class CryptoKeyStore {\n public asymmetricKeys: AsyncMemoryStorage;\n public symmetricKeys: AsyncMemoryStorage;\n public logger: Logger;\n\n constructor(logger: Logger) {\n this.logger = logger;\n this.asymmetricKeys = new AsyncMemoryStorage(\n this.logger,\n CryptoKeyStoreNames.asymmetricKeys\n );\n this.symmetricKeys = new AsyncMemoryStorage(\n this.logger,\n CryptoKeyStoreNames.symmetricKeys\n );\n }\n\n async clear(): Promise {\n // Delete in-memory keystores\n this.asymmetricKeys.clearInMemory();\n this.symmetricKeys.clearInMemory();\n\n /**\n * There is only one database, so calling clearPersistent on asymmetric keystore takes care of\n * every persistent keystore\n */\n try {\n await this.asymmetricKeys.clearPersistent();\n return true;\n } catch (e) {\n if (e instanceof Error) {\n this.logger.error(\n `Clearing keystore failed with error: ${e.message}`\n );\n } else {\n this.logger.error(\n \"Clearing keystore failed with unknown error\"\n );\n }\n\n return false;\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n IPerformanceClient,\n JoseHeader,\n Logger,\n PerformanceEvents,\n PkceCodes,\n SignedHttpRequest,\n SignedHttpRequestParameters,\n} from \"@azure/msal-common\";\nimport { base64Encode, urlEncode, urlEncodeArr } from \"../encode/Base64Encode\";\nimport { base64Decode } from \"../encode/Base64Decode\";\nimport { PkceGenerator } from \"./PkceGenerator\";\nimport { BrowserCrypto } from \"./BrowserCrypto\";\nimport { BrowserStringUtils } from \"../utils/BrowserStringUtils\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { CryptoKeyStore } from \"../cache/CryptoKeyStore\";\n\nexport type CachedKeyPair = {\n publicKey: CryptoKey;\n privateKey: CryptoKey;\n requestMethod?: string;\n requestUri?: string;\n};\n\n/**\n * This class implements MSAL's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and\n * implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636).\n */\nexport class CryptoOps implements ICrypto {\n private browserCrypto: BrowserCrypto;\n private pkceGenerator: PkceGenerator;\n private logger: Logger;\n\n /**\n * CryptoOps can be used in contexts outside a PCA instance,\n * meaning there won't be a performance manager available.\n */\n private performanceClient: IPerformanceClient | undefined;\n\n private static POP_KEY_USAGES: Array = [\"sign\", \"verify\"];\n private static EXTRACTABLE: boolean = true;\n private cache: CryptoKeyStore;\n\n constructor(logger: Logger, performanceClient?: IPerformanceClient) {\n this.logger = logger;\n // Browser crypto needs to be validated first before any other classes can be set.\n this.browserCrypto = new BrowserCrypto(this.logger);\n this.pkceGenerator = new PkceGenerator(this.browserCrypto);\n this.cache = new CryptoKeyStore(this.logger);\n this.performanceClient = performanceClient;\n }\n\n /**\n * Creates a new random GUID - used to populate state and nonce.\n * @returns string (GUID)\n */\n createNewGuid(): string {\n return window.crypto.randomUUID();\n }\n\n /**\n * Encodes input string to base64.\n * @param input\n */\n base64Encode(input: string): string {\n return base64Encode(input);\n }\n\n /**\n * Decodes input string from base64.\n * @param input\n */\n base64Decode(input: string): string {\n return base64Decode(input);\n }\n\n /**\n * Generates PKCE codes used in Authorization Code Flow.\n */\n async generatePkceCodes(): Promise {\n return this.pkceGenerator.generateCodes();\n }\n\n /**\n * Generates a keypair, stores it and returns a thumbprint\n * @param request\n */\n async getPublicKeyThumbprint(\n request: SignedHttpRequestParameters\n ): Promise {\n const publicKeyThumbMeasurement =\n this.performanceClient?.startMeasurement(\n PerformanceEvents.CryptoOptsGetPublicKeyThumbprint,\n request.correlationId\n );\n\n // Generate Keypair\n const keyPair: CryptoKeyPair = await this.browserCrypto.generateKeyPair(\n CryptoOps.EXTRACTABLE,\n CryptoOps.POP_KEY_USAGES\n );\n\n // Generate Thumbprint for Public Key\n const publicKeyJwk: JsonWebKey = await this.browserCrypto.exportJwk(\n keyPair.publicKey\n );\n\n const pubKeyThumprintObj: JsonWebKey = {\n e: publicKeyJwk.e,\n kty: publicKeyJwk.kty,\n n: publicKeyJwk.n,\n };\n\n const publicJwkString: string =\n BrowserStringUtils.getSortedObjectString(pubKeyThumprintObj);\n const publicJwkHash = await this.hashString(publicJwkString);\n\n // Generate Thumbprint for Private Key\n const privateKeyJwk: JsonWebKey = await this.browserCrypto.exportJwk(\n keyPair.privateKey\n );\n // Re-import private key to make it unextractable\n const unextractablePrivateKey: CryptoKey =\n await this.browserCrypto.importJwk(privateKeyJwk, false, [\"sign\"]);\n\n // Store Keypair data in keystore\n await this.cache.asymmetricKeys.setItem(publicJwkHash, {\n privateKey: unextractablePrivateKey,\n publicKey: keyPair.publicKey,\n requestMethod: request.resourceRequestMethod,\n requestUri: request.resourceRequestUri,\n });\n\n if (publicKeyThumbMeasurement) {\n publicKeyThumbMeasurement.end({\n success: true,\n });\n }\n\n return publicJwkHash;\n }\n\n /**\n * Removes cryptographic keypair from key store matching the keyId passed in\n * @param kid\n */\n async removeTokenBindingKey(kid: string): Promise {\n await this.cache.asymmetricKeys.removeItem(kid);\n const keyFound = await this.cache.asymmetricKeys.containsKey(kid);\n return !keyFound;\n }\n\n /**\n * Removes all cryptographic keys from IndexedDB storage\n */\n async clearKeystore(): Promise {\n return await this.cache.clear();\n }\n\n /**\n * Signs the given object as a jwt payload with private key retrieved by given kid.\n * @param payload\n * @param kid\n */\n async signJwt(\n payload: SignedHttpRequest,\n kid: string,\n correlationId?: string\n ): Promise {\n const signJwtMeasurement = this.performanceClient?.startMeasurement(\n PerformanceEvents.CryptoOptsSignJwt,\n correlationId\n );\n const cachedKeyPair = await this.cache.asymmetricKeys.getItem(kid);\n\n if (!cachedKeyPair) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.cryptoKeyNotFound\n );\n }\n\n // Get public key as JWK\n const publicKeyJwk = await this.browserCrypto.exportJwk(\n cachedKeyPair.publicKey\n );\n const publicKeyJwkString =\n BrowserStringUtils.getSortedObjectString(publicKeyJwk);\n\n // Base64URL encode public key thumbprint with keyId only: BASE64URL({ kid: \"FULL_PUBLIC_KEY_HASH\" })\n const encodedKeyIdThumbprint = urlEncode(JSON.stringify({ kid: kid }));\n\n // Generate header\n const shrHeader = JoseHeader.getShrHeaderString({\n kid: encodedKeyIdThumbprint,\n alg: publicKeyJwk.alg,\n });\n const encodedShrHeader = urlEncode(shrHeader);\n\n // Generate payload\n payload.cnf = {\n jwk: JSON.parse(publicKeyJwkString),\n };\n const encodedPayload = urlEncode(JSON.stringify(payload));\n\n // Form token string\n const tokenString = `${encodedShrHeader}.${encodedPayload}`;\n\n // Sign token\n const tokenBuffer = BrowserStringUtils.stringToUtf8Arr(tokenString);\n const signatureBuffer = await this.browserCrypto.sign(\n cachedKeyPair.privateKey,\n tokenBuffer\n );\n const encodedSignature = urlEncodeArr(new Uint8Array(signatureBuffer));\n\n const signedJwt = `${tokenString}.${encodedSignature}`;\n\n if (signJwtMeasurement) {\n signJwtMeasurement.end({\n success: true,\n });\n }\n\n return signedJwt;\n }\n\n /**\n * Returns the SHA-256 hash of an input string\n * @param plainText\n */\n async hashString(plainText: string): Promise {\n const hashBuffer: ArrayBuffer = await this.browserCrypto.sha256Digest(\n plainText\n );\n const hashBytes = new Uint8Array(hashBuffer);\n return urlEncodeArr(hashBytes);\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ServerAuthorizationCodeResponse } from \"../response/ServerAuthorizationCodeResponse\";\nimport { ClientConfigurationError } from \"../error/ClientConfigurationError\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\nimport { StringUtils } from \"../utils/StringUtils\";\nimport { IUri } from \"./IUri\";\nimport {\n AADAuthorityConstants,\n Constants,\n ServerResponseType,\n} from \"../utils/Constants\";\n\n/**\n * Url object class which can perform various transformations on url strings.\n */\nexport class UrlString {\n // internal url string field\n private _urlString: string;\n public get urlString(): string {\n return this._urlString;\n }\n\n constructor(url: string) {\n this._urlString = url;\n if (!this._urlString) {\n // Throws error if url is empty\n throw ClientConfigurationError.createUrlEmptyError();\n }\n\n if (!this.getHash()) {\n this._urlString = UrlString.canonicalizeUri(url);\n }\n }\n\n /**\n * Ensure urls are lower case and end with a / character.\n * @param url\n */\n static canonicalizeUri(url: string): string {\n if (url) {\n let lowerCaseUrl = url.toLowerCase();\n\n if (StringUtils.endsWith(lowerCaseUrl, \"?\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -1);\n } else if (StringUtils.endsWith(lowerCaseUrl, \"?/\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -2);\n }\n\n if (!StringUtils.endsWith(lowerCaseUrl, \"/\")) {\n lowerCaseUrl += \"/\";\n }\n\n return lowerCaseUrl;\n }\n\n return url;\n }\n\n /**\n * Throws if urlString passed is not a valid authority URI string.\n */\n validateAsUri(): void {\n // Attempts to parse url for uri components\n let components;\n try {\n components = this.getUrlComponents();\n } catch (e) {\n throw ClientConfigurationError.createUrlParseError(e as string);\n }\n\n // Throw error if URI or path segments are not parseable.\n if (!components.HostNameAndPort || !components.PathSegments) {\n throw ClientConfigurationError.createUrlParseError(\n `Given url string: ${this.urlString}`\n );\n }\n\n // Throw error if uri is insecure.\n if (\n !components.Protocol ||\n components.Protocol.toLowerCase() !== \"https:\"\n ) {\n throw ClientConfigurationError.createInsecureAuthorityUriError(\n this.urlString\n );\n }\n }\n\n /**\n * Given a url and a query string return the url with provided query string appended\n * @param url\n * @param queryString\n */\n static appendQueryString(url: string, queryString: string): string {\n if (!queryString) {\n return url;\n }\n\n return url.indexOf(\"?\") < 0\n ? `${url}?${queryString}`\n : `${url}&${queryString}`;\n }\n\n /**\n * Returns a url with the hash removed\n * @param url\n */\n static removeHashFromUrl(url: string): string {\n return UrlString.canonicalizeUri(url.split(\"#\")[0]);\n }\n\n /**\n * Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d\n * @param href The url\n * @param tenantId The tenant id to replace\n */\n replaceTenantPath(tenantId: string): UrlString {\n const urlObject = this.getUrlComponents();\n const pathArray = urlObject.PathSegments;\n if (\n tenantId &&\n pathArray.length !== 0 &&\n (pathArray[0] === AADAuthorityConstants.COMMON ||\n pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)\n ) {\n pathArray[0] = tenantId;\n }\n return UrlString.constructAuthorityUriFromObject(urlObject);\n }\n\n /**\n * Returns the anchor part(#) of the URL\n */\n getHash(): string {\n return UrlString.parseHash(this.urlString);\n }\n\n /**\n * Parses out the components from a url string.\n * @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.\n */\n getUrlComponents(): IUri {\n // https://gist.github.com/curtisz/11139b2cfcaef4a261e0\n const regEx = RegExp(\n \"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?\"\n );\n\n // If url string does not match regEx, we throw an error\n const match = this.urlString.match(regEx);\n if (!match) {\n throw ClientConfigurationError.createUrlParseError(\n `Given url string: ${this.urlString}`\n );\n }\n\n // Url component object\n const urlComponents = {\n Protocol: match[1],\n HostNameAndPort: match[4],\n AbsolutePath: match[5],\n QueryString: match[7],\n } as IUri;\n\n let pathSegments = urlComponents.AbsolutePath.split(\"/\");\n pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements\n urlComponents.PathSegments = pathSegments;\n\n if (\n urlComponents.QueryString &&\n urlComponents.QueryString.endsWith(\"/\")\n ) {\n urlComponents.QueryString = urlComponents.QueryString.substring(\n 0,\n urlComponents.QueryString.length - 1\n );\n }\n return urlComponents;\n }\n\n static getDomainFromUrl(url: string): string {\n const regEx = RegExp(\"^([^:/?#]+://)?([^/?#]*)\");\n\n const match = url.match(regEx);\n\n if (!match) {\n throw ClientConfigurationError.createUrlParseError(\n `Given url string: ${url}`\n );\n }\n\n return match[2];\n }\n\n static getAbsoluteUrl(relativeUrl: string, baseUrl: string): string {\n if (relativeUrl[0] === Constants.FORWARD_SLASH) {\n const url = new UrlString(baseUrl);\n const baseComponents = url.getUrlComponents();\n\n return (\n baseComponents.Protocol +\n \"//\" +\n baseComponents.HostNameAndPort +\n relativeUrl\n );\n }\n\n return relativeUrl;\n }\n\n /**\n * Parses hash string from given string. Returns empty string if no hash symbol is found.\n * @param hashString\n */\n static parseHash(hashString: string): string {\n const hashIndex1 = hashString.indexOf(\"#\");\n const hashIndex2 = hashString.indexOf(\"#/\");\n if (hashIndex2 > -1) {\n return hashString.substring(hashIndex2 + 2);\n } else if (hashIndex1 > -1) {\n return hashString.substring(hashIndex1 + 1);\n }\n return Constants.EMPTY_STRING;\n }\n\n /**\n * Parses query string from given string. Returns empty string if no query symbol is found.\n * @param queryString\n */\n static parseQueryString(queryString: string): string {\n const queryIndex1 = queryString.indexOf(\"?\");\n const queryIndex2 = queryString.indexOf(\"/?\");\n if (queryIndex2 > -1) {\n return queryString.substring(queryIndex2 + 2);\n } else if (queryIndex1 > -1) {\n return queryString.substring(queryIndex1 + 1);\n }\n return Constants.EMPTY_STRING;\n }\n\n /**\n * Parses query server response string from given string.\n * Extract hash between '?code=' and '#' if trailing '# is present.\n * Returns empty string if no query symbol is found.\n * @param queryString\n */\n static parseQueryServerResponse(queryString: string): string {\n const queryIndex1 = queryString.indexOf(\"?code\");\n const queryIndex2 = queryString.indexOf(\"/?code\");\n const hashIndex = queryString.indexOf(\"#\");\n if (queryIndex2 > -1 && hashIndex > -1) {\n return queryString.substring(queryIndex2 + 2, hashIndex);\n } else if (queryIndex2 > -1) {\n return queryString.substring(queryIndex2 + 2);\n } else if (queryIndex1 > -1 && hashIndex > -1) {\n return queryString.substring(queryIndex1 + 1, hashIndex);\n } else if (queryIndex1 > -1) {\n return queryString.substring(queryIndex1 + 1);\n }\n return Constants.EMPTY_STRING;\n }\n\n static constructAuthorityUriFromObject(urlObject: IUri): UrlString {\n return new UrlString(\n urlObject.Protocol +\n \"//\" +\n urlObject.HostNameAndPort +\n \"/\" +\n urlObject.PathSegments.join(\"/\")\n );\n }\n\n /**\n * Returns URL hash as server auth code response object.\n */\n static getDeserializedHash(hash: string): ServerAuthorizationCodeResponse {\n // Check if given hash is empty\n if (!hash) {\n return {};\n }\n // Strip the # symbol if present\n const parsedHash = UrlString.parseHash(hash);\n // If # symbol was not present, above will return empty string, so give original hash value\n const deserializedHash: ServerAuthorizationCodeResponse =\n StringUtils.queryStringToObject(\n parsedHash || hash\n );\n // Check if deserialization didn't work\n if (!deserializedHash) {\n throw ClientAuthError.createHashNotDeserializedError(\n JSON.stringify(deserializedHash)\n );\n }\n return deserializedHash;\n }\n\n /**\n * Returns URL query string as server auth code response object.\n */\n static getDeserializedQueryString(\n query: string\n ): ServerAuthorizationCodeResponse {\n // Check if given query is empty\n if (!query) {\n return {};\n }\n // Strip the ? symbol if present\n const parsedQueryString = UrlString.parseQueryString(query);\n // If ? symbol was not present, above will return empty string, so give original query value\n const deserializedQueryString: ServerAuthorizationCodeResponse =\n StringUtils.queryStringToObject(\n parsedQueryString || query\n );\n // Check if deserialization didn't work\n if (!deserializedQueryString) {\n throw ClientAuthError.createHashNotDeserializedError(\n JSON.stringify(deserializedQueryString)\n );\n }\n return deserializedQueryString;\n }\n /**\n * Returns either deserialized query string or deserialized hash, depending on the serverResponseType\n * as a server auth code response object.\n */\n static getDeserializedCodeResponse(\n serverResponseType: ServerResponseType | undefined,\n hashFragment: string\n ): ServerAuthorizationCodeResponse {\n const hashUrlString = new UrlString(hashFragment);\n let serverParams: ServerAuthorizationCodeResponse;\n if (serverResponseType === ServerResponseType.QUERY) {\n serverParams = UrlString.getDeserializedQueryString(hashFragment);\n } else {\n serverParams = UrlString.getDeserializedHash(\n hashUrlString.getHash()\n );\n }\n return serverParams;\n }\n\n /**\n * Check if the hash of the URL string contains known properties\n */\n static hashContainsKnownProperties(hash: string): boolean {\n if (!hash || hash.indexOf(\"=\") < 0) {\n // Hash doesn't contain key/value pairs\n return false;\n }\n\n const parameters: ServerAuthorizationCodeResponse =\n UrlString.getDeserializedHash(hash);\n return !!(\n parameters.code ||\n parameters.error_description ||\n parameters.error ||\n parameters.state\n );\n }\n}\n","import getPrototypeOf from \"./getPrototypeOf.js\";\nexport default function _superPropBase(object, property) {\n while (!Object.prototype.hasOwnProperty.call(object, property)) {\n object = getPrototypeOf(object);\n if (object === null) break;\n }\n return object;\n}","import superPropBase from \"./superPropBase.js\";\nexport default function _get() {\n if (typeof Reflect !== \"undefined\" && Reflect.get) {\n _get = Reflect.get.bind();\n } else {\n _get = function _get(target, property, receiver) {\n var base = superPropBase(target, property);\n if (!base) return;\n var desc = Object.getOwnPropertyDescriptor(base, property);\n if (desc.get) {\n return desc.get.call(arguments.length < 3 ? target : receiver);\n }\n return desc.value;\n };\n }\n return _get.apply(this, arguments);\n}","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Separators,\n CredentialType,\n CacheType,\n Constants,\n AuthenticationScheme,\n} from \"../../utils/Constants\";\nimport { ClientAuthError } from \"../../error/ClientAuthError\";\n\n/**\n * Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc\n *\n * Key:Value Schema:\n *\n * Key: -------\n *\n * Value Schema:\n * {\n * homeAccountId: home account identifier for the auth scheme,\n * environment: entity that issued the token, represented as a full host\n * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other\n * clientId: client ID of the application\n * secret: Actual credential as a string\n * familyId: Family ID identifier, usually only used for refresh tokens\n * realm: Full tenant or organizational identifier that the account belongs to\n * target: Permissions that are included in the token, or for refresh tokens, the resource identifier.\n * tokenType: Matches the authentication scheme for which the token was issued (i.e. Bearer or pop)\n * requestedClaimsHash: Matches the SHA 256 hash of the claims object included in the token request\n * userAssertionHash: Matches the SHA 256 hash of the obo_assertion for the OBO flow\n * }\n */\nexport class CredentialEntity {\n homeAccountId: string;\n environment: string;\n credentialType: CredentialType;\n clientId: string;\n secret: string;\n familyId?: string;\n realm?: string;\n target?: string;\n userAssertionHash?: string;\n tokenType?: AuthenticationScheme;\n keyId?: string;\n requestedClaimsHash?: string;\n\n /**\n * Generate Account Id key component as per the schema: -\n */\n generateAccountId(): string {\n return CredentialEntity.generateAccountIdForCacheKey(\n this.homeAccountId,\n this.environment\n );\n }\n\n /**\n * Generate Credential Id key component as per the schema: --\n */\n generateCredentialId(): string {\n return CredentialEntity.generateCredentialIdForCacheKey(\n this.credentialType,\n this.clientId,\n this.realm,\n this.familyId\n );\n }\n\n /**\n * Generate target key component as per schema: \n */\n generateTarget(): string {\n return CredentialEntity.generateTargetForCacheKey(this.target);\n }\n\n /**\n * generates credential key\n */\n generateCredentialKey(): string {\n return CredentialEntity.generateCredentialCacheKey(\n this.homeAccountId,\n this.environment,\n this.credentialType,\n this.clientId,\n this.realm,\n this.target,\n this.familyId,\n this.tokenType,\n this.requestedClaimsHash\n );\n }\n\n /**\n * returns the type of the cache (in this case credential)\n */\n generateType(): number {\n switch (this.credentialType) {\n case CredentialType.ID_TOKEN:\n return CacheType.ID_TOKEN;\n case CredentialType.ACCESS_TOKEN:\n case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME:\n return CacheType.ACCESS_TOKEN;\n case CredentialType.REFRESH_TOKEN:\n return CacheType.REFRESH_TOKEN;\n default: {\n throw ClientAuthError.createUnexpectedCredentialTypeError();\n }\n }\n }\n\n /**\n * generates credential key\n * -\\-----\n */\n static generateCredentialCacheKey(\n homeAccountId: string,\n environment: string,\n credentialType: CredentialType,\n clientId: string,\n realm?: string,\n target?: string,\n familyId?: string,\n tokenType?: AuthenticationScheme,\n requestedClaimsHash?: string\n ): string {\n const credentialKey = [\n this.generateAccountIdForCacheKey(homeAccountId, environment),\n this.generateCredentialIdForCacheKey(\n credentialType,\n clientId,\n realm,\n familyId\n ),\n this.generateTargetForCacheKey(target),\n this.generateClaimsHashForCacheKey(requestedClaimsHash),\n this.generateSchemeForCacheKey(tokenType),\n ];\n\n return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();\n }\n\n /**\n * generates Account Id for keys\n * @param homeAccountId\n * @param environment\n */\n private static generateAccountIdForCacheKey(\n homeAccountId: string,\n environment: string\n ): string {\n const accountId: Array = [homeAccountId, environment];\n return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();\n }\n\n /**\n * Generates Credential Id for keys\n * @param credentialType\n * @param realm\n * @param clientId\n * @param familyId\n */\n private static generateCredentialIdForCacheKey(\n credentialType: CredentialType,\n clientId: string,\n realm?: string,\n familyId?: string\n ): string {\n const clientOrFamilyId =\n credentialType === CredentialType.REFRESH_TOKEN\n ? familyId || clientId\n : clientId;\n const credentialId: Array = [\n credentialType,\n clientOrFamilyId,\n realm || Constants.EMPTY_STRING,\n ];\n\n return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();\n }\n\n /**\n * Generate target key component as per schema: \n */\n private static generateTargetForCacheKey(scopes?: string): string {\n return (scopes || Constants.EMPTY_STRING).toLowerCase();\n }\n\n /**\n * Generate requested claims key component as per schema: \n */\n private static generateClaimsHashForCacheKey(\n requestedClaimsHash?: string\n ): string {\n return (requestedClaimsHash || Constants.EMPTY_STRING).toLowerCase();\n }\n\n /**\n * Generate scheme key componenet as per schema: \n */\n private static generateSchemeForCacheKey(tokenType?: string): string {\n /*\n * PoP Tokens and SSH certs include scheme in cache key\n * Cast to lowercase to handle \"bearer\" from ADFS\n */\n return tokenType &&\n tokenType.toLowerCase() !==\n AuthenticationScheme.BEARER.toLowerCase()\n ? tokenType.toLowerCase()\n : Constants.EMPTY_STRING;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CredentialEntity } from \"./CredentialEntity\";\nimport { CredentialType } from \"../../utils/Constants\";\n\n/**\n * ID_TOKEN Cache\n *\n * Key:Value Schema:\n *\n * Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com-\n *\n * Value Schema:\n * {\n * homeAccountId: home account identifier for the auth scheme,\n * environment: entity that issued the token, represented as a full host\n * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other\n * clientId: client ID of the application\n * secret: Actual credential as a string\n * realm: Full tenant or organizational identifier that the account belongs to\n * }\n */\nexport class IdTokenEntity extends CredentialEntity {\n realm: string;\n\n /**\n * Create IdTokenEntity\n * @param homeAccountId\n * @param authenticationResult\n * @param clientId\n * @param authority\n */\n static createIdTokenEntity(\n homeAccountId: string,\n environment: string,\n idToken: string,\n clientId: string,\n tenantId: string\n ): IdTokenEntity {\n const idTokenEntity = new IdTokenEntity();\n\n idTokenEntity.credentialType = CredentialType.ID_TOKEN;\n idTokenEntity.homeAccountId = homeAccountId;\n idTokenEntity.environment = environment;\n idTokenEntity.clientId = clientId;\n idTokenEntity.secret = idToken;\n idTokenEntity.realm = tenantId;\n\n return idTokenEntity;\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isIdTokenEntity(entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n entity.hasOwnProperty(\"homeAccountId\") &&\n entity.hasOwnProperty(\"environment\") &&\n entity.hasOwnProperty(\"credentialType\") &&\n entity.hasOwnProperty(\"realm\") &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"secret\") &&\n entity[\"credentialType\"] === CredentialType.ID_TOKEN\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Utility class which exposes functions for managing date and time operations.\n */\nexport class TimeUtils {\n /**\n * return the current time in Unix time (seconds).\n */\n static nowSeconds(): number {\n // Date.getTime() returns in milliseconds.\n return Math.round(new Date().getTime() / 1000.0);\n }\n\n /**\n * check if a token is expired based on given UTC time in seconds.\n * @param expiresOn\n */\n static isTokenExpired(expiresOn: string, offset: number): boolean {\n // check for access token expiry\n const expirationSec = Number(expiresOn) || 0;\n const offsetCurrentTimeSec = TimeUtils.nowSeconds() + offset;\n\n // If current time + offset is greater than token expiration time, then token is expired.\n return offsetCurrentTimeSec > expirationSec;\n }\n\n /**\n * If the current time is earlier than the time that a token was cached at, we must discard the token\n * i.e. The system clock was turned back after acquiring the cached token\n * @param cachedAt\n * @param offset\n */\n static wasClockTurnedBack(cachedAt: string): boolean {\n const cachedAtSec = Number(cachedAt);\n\n return cachedAtSec > TimeUtils.nowSeconds();\n }\n\n /**\n * Waits for t number of milliseconds\n * @param t number\n * @param value T\n */\n static delay(t: number, value?: T): Promise {\n return new Promise((resolve) => setTimeout(() => resolve(value), t));\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CredentialEntity } from \"./CredentialEntity\";\nimport { CredentialType, AuthenticationScheme } from \"../../utils/Constants\";\nimport { TimeUtils } from \"../../utils/TimeUtils\";\nimport { ICrypto } from \"../../crypto/ICrypto\";\nimport { TokenClaims } from \"../../account/TokenClaims\";\nimport { ClientAuthError } from \"../../error/ClientAuthError\";\nimport { extractTokenClaims } from \"../../account/AuthToken\";\n\n/**\n * ACCESS_TOKEN Credential Type\n *\n * Key:Value Schema:\n *\n * Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read\n *\n * Value Schema:\n * {\n * homeAccountId: home account identifier for the auth scheme,\n * environment: entity that issued the token, represented as a full host\n * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other\n * clientId: client ID of the application\n * secret: Actual credential as a string\n * familyId: Family ID identifier, usually only used for refresh tokens\n * realm: Full tenant or organizational identifier that the account belongs to\n * target: Permissions that are included in the token, or for refresh tokens, the resource identifier.\n * cachedAt: Absolute device time when entry was created in the cache.\n * expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string.\n * extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds.\n * keyId: used for POP and SSH tokenTypes\n * tokenType: Type of the token issued. Usually \"Bearer\"\n * }\n */\nexport class AccessTokenEntity extends CredentialEntity {\n realm: string;\n target: string;\n cachedAt: string;\n expiresOn: string;\n extendedExpiresOn?: string;\n refreshOn?: string;\n keyId?: string; // for POP and SSH tokenTypes\n tokenType?: AuthenticationScheme;\n requestedClaims?: string;\n requestedClaimsHash?: string;\n\n /**\n * Create AccessTokenEntity\n * @param homeAccountId\n * @param environment\n * @param accessToken\n * @param clientId\n * @param tenantId\n * @param scopes\n * @param expiresOn\n * @param extExpiresOn\n */\n static createAccessTokenEntity(\n homeAccountId: string,\n environment: string,\n accessToken: string,\n clientId: string,\n tenantId: string,\n scopes: string,\n expiresOn: number,\n extExpiresOn: number,\n cryptoUtils: ICrypto,\n refreshOn?: number,\n tokenType?: AuthenticationScheme,\n userAssertionHash?: string,\n keyId?: string,\n requestedClaims?: string,\n requestedClaimsHash?: string\n ): AccessTokenEntity {\n const atEntity: AccessTokenEntity = new AccessTokenEntity();\n\n atEntity.homeAccountId = homeAccountId;\n atEntity.credentialType = CredentialType.ACCESS_TOKEN;\n atEntity.secret = accessToken;\n\n const currentTime = TimeUtils.nowSeconds();\n atEntity.cachedAt = currentTime.toString();\n\n /*\n * Token expiry time.\n * This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.\n */\n atEntity.expiresOn = expiresOn.toString();\n atEntity.extendedExpiresOn = extExpiresOn.toString();\n if (refreshOn) {\n atEntity.refreshOn = refreshOn.toString();\n }\n\n atEntity.environment = environment;\n atEntity.clientId = clientId;\n atEntity.realm = tenantId;\n atEntity.target = scopes;\n atEntity.userAssertionHash = userAssertionHash;\n\n atEntity.tokenType = tokenType || AuthenticationScheme.BEARER;\n\n if (requestedClaims) {\n atEntity.requestedClaims = requestedClaims;\n atEntity.requestedClaimsHash = requestedClaimsHash;\n }\n\n /*\n * Create Access Token With Auth Scheme instead of regular access token\n * Cast to lower to handle \"bearer\" from ADFS\n */\n if (\n atEntity.tokenType?.toLowerCase() !==\n AuthenticationScheme.BEARER.toLowerCase()\n ) {\n atEntity.credentialType =\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;\n switch (atEntity.tokenType) {\n case AuthenticationScheme.POP:\n // Make sure keyId is present and add it to credential\n const tokenClaims: TokenClaims | null = extractTokenClaims(\n accessToken,\n cryptoUtils.base64Decode\n );\n if (!tokenClaims?.cnf?.kid) {\n throw ClientAuthError.createTokenClaimsRequiredError();\n }\n atEntity.keyId = tokenClaims.cnf.kid;\n break;\n case AuthenticationScheme.SSH:\n atEntity.keyId = keyId;\n }\n }\n\n return atEntity;\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isAccessTokenEntity(entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n entity.hasOwnProperty(\"homeAccountId\") &&\n entity.hasOwnProperty(\"environment\") &&\n entity.hasOwnProperty(\"credentialType\") &&\n entity.hasOwnProperty(\"realm\") &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"secret\") &&\n entity.hasOwnProperty(\"target\") &&\n (entity[\"credentialType\"] === CredentialType.ACCESS_TOKEN ||\n entity[\"credentialType\"] ===\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CredentialEntity } from \"./CredentialEntity\";\nimport { CredentialType } from \"../../utils/Constants\";\n\n/**\n * REFRESH_TOKEN Cache\n *\n * Key:Value Schema:\n *\n * Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId--\n *\n * Value:\n * {\n * homeAccountId: home account identifier for the auth scheme,\n * environment: entity that issued the token, represented as a full host\n * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other\n * clientId: client ID of the application\n * secret: Actual credential as a string\n * familyId: Family ID identifier, '1' represents Microsoft Family\n * realm: Full tenant or organizational identifier that the account belongs to\n * target: Permissions that are included in the token, or for refresh tokens, the resource identifier.\n * }\n */\nexport class RefreshTokenEntity extends CredentialEntity {\n familyId?: string;\n\n /**\n * Create RefreshTokenEntity\n * @param homeAccountId\n * @param authenticationResult\n * @param clientId\n * @param authority\n */\n static createRefreshTokenEntity(\n homeAccountId: string,\n environment: string,\n refreshToken: string,\n clientId: string,\n familyId?: string,\n userAssertionHash?: string\n ): RefreshTokenEntity {\n const rtEntity = new RefreshTokenEntity();\n\n rtEntity.clientId = clientId;\n rtEntity.credentialType = CredentialType.REFRESH_TOKEN;\n rtEntity.environment = environment;\n rtEntity.homeAccountId = homeAccountId;\n rtEntity.secret = refreshToken;\n rtEntity.userAssertionHash = userAssertionHash;\n\n if (familyId) rtEntity.familyId = familyId;\n\n return rtEntity;\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isRefreshTokenEntity(entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n entity.hasOwnProperty(\"homeAccountId\") &&\n entity.hasOwnProperty(\"environment\") &&\n entity.hasOwnProperty(\"credentialType\") &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"secret\") &&\n entity[\"credentialType\"] === CredentialType.REFRESH_TOKEN\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { APP_METADATA, Separators } from \"../../utils/Constants\";\n\n/**\n * APP_METADATA Cache\n *\n * Key:Value Schema:\n *\n * Key: appmetadata--\n *\n * Value:\n * {\n * clientId: client ID of the application\n * environment: entity that issued the token, represented as a full host\n * familyId: Family ID identifier, '1' represents Microsoft Family\n * }\n */\nexport class AppMetadataEntity {\n clientId: string;\n environment: string;\n familyId?: string;\n\n /**\n * Generate AppMetadata Cache Key as per the schema: appmetadata--\n */\n generateAppMetadataKey(): string {\n return AppMetadataEntity.generateAppMetadataCacheKey(\n this.environment,\n this.clientId\n );\n }\n\n /**\n * Generate AppMetadata Cache Key\n */\n static generateAppMetadataCacheKey(\n environment: string,\n clientId: string\n ): string {\n const appMetaDataKeyArray: Array = [\n APP_METADATA,\n environment,\n clientId,\n ];\n return appMetaDataKeyArray\n .join(Separators.CACHE_KEY_SEPARATOR)\n .toLowerCase();\n }\n\n /**\n * Creates AppMetadataEntity\n * @param clientId\n * @param environment\n * @param familyId\n */\n static createAppMetadataEntity(\n clientId: string,\n environment: string,\n familyId?: string\n ): AppMetadataEntity {\n const appMetadata = new AppMetadataEntity();\n\n appMetadata.clientId = clientId;\n appMetadata.environment = environment;\n if (familyId) {\n appMetadata.familyId = familyId;\n }\n\n return appMetadata;\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isAppMetadataEntity(key: string, entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n key.indexOf(APP_METADATA) === 0 &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"environment\")\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { SERVER_TELEM_CONSTANTS } from \"../../utils/Constants\";\n\nexport class ServerTelemetryEntity {\n failedRequests: Array;\n errors: string[];\n cacheHits: number;\n\n constructor() {\n this.failedRequests = [];\n this.errors = [];\n this.cacheHits = 0;\n }\n\n /**\n * validates if a given cache entry is \"Telemetry\", parses \n * @param key\n * @param entity\n */\n static isServerTelemetryEntity(key: string, entity?: object): boolean {\n const validateKey: boolean =\n key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0;\n let validateEntity: boolean = true;\n\n if (entity) {\n validateEntity =\n entity.hasOwnProperty(\"failedRequests\") &&\n entity.hasOwnProperty(\"errors\") &&\n entity.hasOwnProperty(\"cacheHits\");\n }\n\n return validateKey && validateEntity;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CloudDiscoveryMetadata } from \"../../authority/CloudDiscoveryMetadata\";\nimport { OpenIdConfigResponse } from \"../../authority/OpenIdConfigResponse\";\nimport { AUTHORITY_METADATA_CONSTANTS } from \"../../utils/Constants\";\nimport { TimeUtils } from \"../../utils/TimeUtils\";\n\n/** @internal */\nexport class AuthorityMetadataEntity {\n aliases: Array;\n preferred_cache: string;\n preferred_network: string;\n canonical_authority: string;\n authorization_endpoint: string;\n token_endpoint: string;\n end_session_endpoint?: string;\n issuer: string;\n aliasesFromNetwork: boolean;\n endpointsFromNetwork: boolean;\n expiresAt: number;\n jwks_uri: string;\n\n constructor() {\n this.expiresAt =\n TimeUtils.nowSeconds() +\n AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS;\n }\n\n /**\n * Update the entity with new aliases, preferred_cache and preferred_network values\n * @param metadata\n * @param fromNetwork\n */\n updateCloudDiscoveryMetadata(\n metadata: CloudDiscoveryMetadata,\n fromNetwork: boolean\n ): void {\n this.aliases = metadata.aliases;\n this.preferred_cache = metadata.preferred_cache;\n this.preferred_network = metadata.preferred_network;\n this.aliasesFromNetwork = fromNetwork;\n }\n\n /**\n * Update the entity with new endpoints\n * @param metadata\n * @param fromNetwork\n */\n updateEndpointMetadata(\n metadata: OpenIdConfigResponse,\n fromNetwork: boolean\n ): void {\n this.authorization_endpoint = metadata.authorization_endpoint;\n this.token_endpoint = metadata.token_endpoint;\n this.end_session_endpoint = metadata.end_session_endpoint;\n this.issuer = metadata.issuer;\n this.endpointsFromNetwork = fromNetwork;\n this.jwks_uri = metadata.jwks_uri;\n }\n\n /**\n * Save the authority that was used to create this cache entry\n * @param authority\n */\n updateCanonicalAuthority(authority: string): void {\n this.canonical_authority = authority;\n }\n\n /**\n * Reset the exiresAt value\n */\n resetExpiresAt(): void {\n this.expiresAt =\n TimeUtils.nowSeconds() +\n AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS;\n }\n\n /**\n * Returns whether or not the data needs to be refreshed\n */\n isExpired(): boolean {\n return this.expiresAt <= TimeUtils.nowSeconds();\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isAuthorityMetadataEntity(key: string, entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 &&\n entity.hasOwnProperty(\"aliases\") &&\n entity.hasOwnProperty(\"preferred_cache\") &&\n entity.hasOwnProperty(\"preferred_network\") &&\n entity.hasOwnProperty(\"canonical_authority\") &&\n entity.hasOwnProperty(\"authorization_endpoint\") &&\n entity.hasOwnProperty(\"token_endpoint\") &&\n entity.hasOwnProperty(\"issuer\") &&\n entity.hasOwnProperty(\"aliasesFromNetwork\") &&\n entity.hasOwnProperty(\"endpointsFromNetwork\") &&\n entity.hasOwnProperty(\"expiresAt\") &&\n entity.hasOwnProperty(\"jwks_uri\")\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ThrottlingConstants } from \"../../utils/Constants\";\n\nexport class ThrottlingEntity {\n // Unix-time value representing the expiration of the throttle\n throttleTime: number;\n // Information provided by the server\n error?: string;\n errorCodes?: Array;\n errorMessage?: string;\n subError?: string;\n\n /**\n * validates if a given cache entry is \"Throttling\", parses \n * @param key\n * @param entity\n */\n static isThrottlingEntity(key: string, entity?: object): boolean {\n let validateKey: boolean = false;\n if (key) {\n validateKey =\n key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;\n }\n\n let validateEntity: boolean = true;\n if (entity) {\n validateEntity = entity.hasOwnProperty(\"throttleTime\");\n }\n\n return validateKey && validateEntity;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants } from \"./Constants\";\nimport { ICrypto } from \"../crypto/ICrypto\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\n\n/**\n * Type which defines the object that is stringified, encoded and sent in the state value.\n * Contains the following:\n * - id - unique identifier for this request\n * - ts - timestamp for the time the request was made. Used to ensure that token expiration is not calculated incorrectly.\n * - platformState - string value sent from the platform.\n */\nexport type LibraryStateObject = {\n id: string;\n meta?: Record;\n};\n\n/**\n * Type which defines the stringified and encoded object sent to the service in the authorize request.\n */\nexport type RequestStateObject = {\n userRequestState: string;\n libraryState: LibraryStateObject;\n};\n\n/**\n * Class which provides helpers for OAuth 2.0 protocol specific values\n */\nexport class ProtocolUtils {\n /**\n * Appends user state with random guid, or returns random guid.\n * @param userState\n * @param randomGuid\n */\n static setRequestState(\n cryptoObj: ICrypto,\n userState?: string,\n meta?: Record\n ): string {\n const libraryState = ProtocolUtils.generateLibraryState(\n cryptoObj,\n meta\n );\n return userState\n ? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`\n : libraryState;\n }\n\n /**\n * Generates the state value used by the common library.\n * @param randomGuid\n * @param cryptoObj\n */\n static generateLibraryState(\n cryptoObj: ICrypto,\n meta?: Record\n ): string {\n if (!cryptoObj) {\n throw ClientAuthError.createNoCryptoObjectError(\n \"generateLibraryState\"\n );\n }\n\n // Create a state object containing a unique id and the timestamp of the request creation\n const stateObj: LibraryStateObject = {\n id: cryptoObj.createNewGuid(),\n };\n\n if (meta) {\n stateObj.meta = meta;\n }\n\n const stateString = JSON.stringify(stateObj);\n\n return cryptoObj.base64Encode(stateString);\n }\n\n /**\n * Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.\n * @param state\n * @param cryptoObj\n */\n static parseRequestState(\n cryptoObj: ICrypto,\n state: string\n ): RequestStateObject {\n if (!cryptoObj) {\n throw ClientAuthError.createNoCryptoObjectError(\n \"parseRequestState\"\n );\n }\n\n if (!state) {\n throw ClientAuthError.createInvalidStateError(\n state,\n \"Null, undefined or empty state\"\n );\n }\n\n try {\n // Split the state between library state and user passed state and decode them separately\n const splitState = state.split(Constants.RESOURCE_DELIM);\n const libraryState = splitState[0];\n const userState =\n splitState.length > 1\n ? splitState.slice(1).join(Constants.RESOURCE_DELIM)\n : Constants.EMPTY_STRING;\n const libraryStateString = cryptoObj.base64Decode(libraryState);\n const libraryStateObj = JSON.parse(\n libraryStateString\n ) as LibraryStateObject;\n return {\n userRequestState: userState || Constants.EMPTY_STRING,\n libraryState: libraryStateObj,\n };\n } catch (e) {\n throw ClientAuthError.createInvalidStateError(state, e as string);\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type CcsCredential = {\n credential: string;\n type: CcsCredentialType;\n};\n\nexport const CcsCredentialType = {\n HOME_ACCOUNT_ID: \"home_account_id\",\n UPN: \"UPN\",\n} as const;\nexport type CcsCredentialType =\n (typeof CcsCredentialType)[keyof typeof CcsCredentialType];\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IdTokenEntity } from \"./IdTokenEntity\";\nimport { AccessTokenEntity } from \"./AccessTokenEntity\";\nimport { RefreshTokenEntity } from \"./RefreshTokenEntity\";\nimport { AccountEntity } from \"./AccountEntity\";\nimport { AppMetadataEntity } from \"./AppMetadataEntity\";\n\n/** @internal */\nexport class CacheRecord {\n account: AccountEntity | null;\n idToken: IdTokenEntity | null;\n accessToken: AccessTokenEntity | null;\n refreshToken: RefreshTokenEntity | null;\n appMetadata: AppMetadataEntity | null;\n\n constructor(\n accountEntity?: AccountEntity | null,\n idTokenEntity?: IdTokenEntity | null,\n accessTokenEntity?: AccessTokenEntity | null,\n refreshTokenEntity?: RefreshTokenEntity | null,\n appMetadataEntity?: AppMetadataEntity | null\n ) {\n this.account = accountEntity || null;\n this.idToken = idTokenEntity || null;\n this.accessToken = accessTokenEntity || null;\n this.refreshToken = refreshTokenEntity || null;\n this.appMetadata = appMetadataEntity || null;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BrowserConfigurationAuthError } from \"../error/BrowserConfigurationAuthError\";\nimport { BrowserCacheLocation } from \"../utils/BrowserConstants\";\nimport { IWindowStorage } from \"./IWindowStorage\";\n\nexport class BrowserStorage implements IWindowStorage {\n private windowStorage: Storage;\n\n constructor(cacheLocation: string) {\n this.validateWindowStorage(cacheLocation);\n this.windowStorage = window[cacheLocation];\n }\n\n private validateWindowStorage(cacheLocation: string): void {\n if (\n cacheLocation !== BrowserCacheLocation.LocalStorage &&\n cacheLocation !== BrowserCacheLocation.SessionStorage\n ) {\n throw BrowserConfigurationAuthError.createStorageNotSupportedError(\n cacheLocation\n );\n }\n const storageSupported = !!window[cacheLocation];\n if (!storageSupported) {\n throw BrowserConfigurationAuthError.createStorageNotSupportedError(\n cacheLocation\n );\n }\n }\n\n getItem(key: string): string | null {\n return this.windowStorage.getItem(key);\n }\n\n setItem(key: string, value: string): void {\n this.windowStorage.setItem(key, value);\n }\n\n removeItem(key: string): void {\n this.windowStorage.removeItem(key);\n }\n\n getKeys(): string[] {\n return Object.keys(this.windowStorage);\n }\n\n containsKey(key: string): boolean {\n return this.windowStorage.hasOwnProperty(key);\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { InteractionType } from \"./BrowserConstants\";\nimport {\n ClientAuthError,\n ICrypto,\n RequestStateObject,\n ProtocolUtils,\n ServerAuthorizationCodeResponse,\n UrlString,\n} from \"@azure/msal-common\";\n\nexport type BrowserStateObject = {\n interactionType: InteractionType;\n};\n\nexport class BrowserProtocolUtils {\n /**\n * Extracts the BrowserStateObject from the state string.\n * @param browserCrypto\n * @param state\n */\n static extractBrowserRequestState(\n browserCrypto: ICrypto,\n state: string\n ): BrowserStateObject | null {\n if (!state) {\n return null;\n }\n\n try {\n const requestStateObj: RequestStateObject =\n ProtocolUtils.parseRequestState(browserCrypto, state);\n return requestStateObj.libraryState.meta as BrowserStateObject;\n } catch (e) {\n throw ClientAuthError.createInvalidStateError(state, e as string);\n }\n }\n\n /**\n * Parses properties of server response from url hash\n * @param locationHash Hash from url\n */\n static parseServerResponseFromHash(\n locationHash: string\n ): ServerAuthorizationCodeResponse {\n if (!locationHash) {\n return {};\n }\n\n const hashUrlString = new UrlString(locationHash);\n return UrlString.getDeserializedHash(hashUrlString.getHash());\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Constants,\n PersistentCacheKeys,\n StringUtils,\n CommonAuthorizationCodeRequest,\n ICrypto,\n AccountEntity,\n IdTokenEntity,\n AccessTokenEntity,\n RefreshTokenEntity,\n AppMetadataEntity,\n CacheManager,\n ServerTelemetryEntity,\n ThrottlingEntity,\n ProtocolUtils,\n Logger,\n AuthorityMetadataEntity,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n AccountInfo,\n ActiveAccountFilters,\n CcsCredential,\n CcsCredentialType,\n AuthToken,\n ValidCredentialType,\n ClientAuthError,\n TokenKeys,\n CredentialType,\n CacheRecord,\n AuthenticationScheme,\n} from \"@azure/msal-common\";\nimport { CacheOptions } from \"../config/Configuration\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport {\n BrowserCacheLocation,\n InteractionType,\n TemporaryCacheKeys,\n InMemoryCacheKeys,\n StaticCacheKeys,\n} from \"../utils/BrowserConstants\";\nimport { BrowserStorage } from \"./BrowserStorage\";\nimport { MemoryStorage } from \"./MemoryStorage\";\nimport { IWindowStorage } from \"./IWindowStorage\";\nimport { BrowserProtocolUtils } from \"../utils/BrowserProtocolUtils\";\nimport { NativeTokenRequest } from \"../broker/nativeBroker/NativeRequest\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult\";\nimport { SilentRequest } from \"../request/SilentRequest\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest\";\nimport { RedirectRequest } from \"../request/RedirectRequest\";\nimport { PopupRequest } from \"../request/PopupRequest\";\nimport { base64Decode } from \"../encode/Base64Decode\";\nimport { base64Encode } from \"../encode/Base64Encode\";\n\n/**\n * This class implements the cache storage interface for MSAL through browser local or session storage.\n * Cookies are only used if storeAuthStateInCookie is true, and are only used for\n * parameters such as state and nonce, generally.\n */\nexport class BrowserCacheManager extends CacheManager {\n // Cache configuration, either set by user or default values.\n protected cacheConfig: Required;\n // Window storage object (either local or sessionStorage)\n protected browserStorage: IWindowStorage;\n // Internal in-memory storage object used for data used by msal that does not need to persist across page loads\n protected internalStorage: MemoryStorage;\n // Temporary cache\n protected temporaryCacheStorage: IWindowStorage;\n // Logger instance\n protected logger: Logger;\n\n // Cookie life calculation (hours * minutes * seconds * ms)\n protected readonly COOKIE_LIFE_MULTIPLIER = 24 * 60 * 60 * 1000;\n\n constructor(\n clientId: string,\n cacheConfig: Required,\n cryptoImpl: ICrypto,\n logger: Logger\n ) {\n super(clientId, cryptoImpl, logger);\n this.cacheConfig = cacheConfig;\n this.logger = logger;\n this.internalStorage = new MemoryStorage();\n this.browserStorage = this.setupBrowserStorage(\n this.cacheConfig.cacheLocation\n );\n this.temporaryCacheStorage = this.setupTemporaryCacheStorage(\n this.cacheConfig.temporaryCacheLocation,\n this.cacheConfig.cacheLocation\n );\n\n // Migrate cache entries from older versions of MSAL.\n if (cacheConfig.cacheMigrationEnabled) {\n this.migrateCacheEntries();\n this.createKeyMaps();\n }\n }\n\n /**\n * Returns a window storage class implementing the IWindowStorage interface that corresponds to the configured cacheLocation.\n * @param cacheLocation\n */\n protected setupBrowserStorage(\n cacheLocation: BrowserCacheLocation | string\n ): IWindowStorage {\n switch (cacheLocation) {\n case BrowserCacheLocation.LocalStorage:\n case BrowserCacheLocation.SessionStorage:\n try {\n return new BrowserStorage(cacheLocation);\n } catch (e) {\n this.logger.verbose(e as string);\n break;\n }\n case BrowserCacheLocation.MemoryStorage:\n default:\n break;\n }\n this.cacheConfig.cacheLocation = BrowserCacheLocation.MemoryStorage;\n return new MemoryStorage();\n }\n\n /**\n * Returns a window storage class implementing the IWindowStorage interface that corresponds to the configured temporaryCacheLocation.\n * @param temporaryCacheLocation\n * @param cacheLocation\n */\n protected setupTemporaryCacheStorage(\n temporaryCacheLocation: BrowserCacheLocation | string,\n cacheLocation: BrowserCacheLocation | string\n ): IWindowStorage {\n switch (cacheLocation) {\n case BrowserCacheLocation.LocalStorage:\n case BrowserCacheLocation.SessionStorage:\n try {\n // Temporary cache items will always be stored in session storage to mitigate problems caused by multiple tabs\n return new BrowserStorage(\n temporaryCacheLocation ||\n BrowserCacheLocation.SessionStorage\n );\n } catch (e) {\n this.logger.verbose(e as string);\n return this.internalStorage;\n }\n case BrowserCacheLocation.MemoryStorage:\n default:\n return this.internalStorage;\n }\n }\n\n /**\n * Migrate all old cache entries to new schema. No rollback supported.\n * @param storeAuthStateInCookie\n */\n protected migrateCacheEntries(): void {\n const idTokenKey = `${Constants.CACHE_PREFIX}.${PersistentCacheKeys.ID_TOKEN}`;\n const clientInfoKey = `${Constants.CACHE_PREFIX}.${PersistentCacheKeys.CLIENT_INFO}`;\n const errorKey = `${Constants.CACHE_PREFIX}.${PersistentCacheKeys.ERROR}`;\n const errorDescKey = `${Constants.CACHE_PREFIX}.${PersistentCacheKeys.ERROR_DESC}`;\n\n const idTokenValue = this.browserStorage.getItem(idTokenKey);\n const clientInfoValue = this.browserStorage.getItem(clientInfoKey);\n const errorValue = this.browserStorage.getItem(errorKey);\n const errorDescValue = this.browserStorage.getItem(errorDescKey);\n\n const values = [\n idTokenValue,\n clientInfoValue,\n errorValue,\n errorDescValue,\n ];\n const keysToMigrate = [\n PersistentCacheKeys.ID_TOKEN,\n PersistentCacheKeys.CLIENT_INFO,\n PersistentCacheKeys.ERROR,\n PersistentCacheKeys.ERROR_DESC,\n ];\n\n keysToMigrate.forEach((cacheKey: string, index: number) =>\n this.migrateCacheEntry(cacheKey, values[index])\n );\n }\n\n /**\n * Utility function to help with migration.\n * @param newKey\n * @param value\n * @param storeAuthStateInCookie\n */\n protected migrateCacheEntry(newKey: string, value: string | null): void {\n if (value) {\n this.setTemporaryCache(newKey, value, true);\n }\n }\n\n /**\n * Searches all cache entries for MSAL accounts and creates the account key map\n * This is used to migrate users from older versions of MSAL which did not create the map.\n * @returns\n */\n private createKeyMaps(): void {\n this.logger.trace(\"BrowserCacheManager - createKeyMaps called.\");\n const accountKeys = this.getItem(StaticCacheKeys.ACCOUNT_KEYS);\n const tokenKeys = this.getItem(\n `${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`\n );\n if (accountKeys && tokenKeys) {\n this.logger.verbose(\n \"BrowserCacheManager:createKeyMaps - account and token key maps already exist, skipping migration.\"\n );\n // Key maps already exist, no need to iterate through cache\n return;\n }\n\n const allKeys = this.browserStorage.getKeys();\n allKeys.forEach((key) => {\n if (this.isCredentialKey(key)) {\n // Get item, parse, validate and write key to map\n const value = this.getItem(key);\n if (value) {\n const credObj = this.validateAndParseJson(value);\n if (credObj && credObj.hasOwnProperty(\"credentialType\")) {\n switch (credObj[\"credentialType\"]) {\n case CredentialType.ID_TOKEN:\n if (IdTokenEntity.isIdTokenEntity(credObj)) {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - idToken found, saving key to token key map\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - idToken with key: ${key} found, saving key to token key map`\n );\n const idTokenEntity = CacheManager.toObject(\n new IdTokenEntity(),\n credObj\n );\n const newKey =\n this.updateCredentialCacheKey(\n key,\n idTokenEntity\n );\n this.addTokenKey(\n newKey,\n CredentialType.ID_TOKEN\n );\n return;\n } else {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - key found matching idToken schema with value containing idToken credentialType field but value failed IdTokenEntity validation, skipping.\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - failed idToken validation on key: ${key}`\n );\n }\n break;\n case CredentialType.ACCESS_TOKEN:\n case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME:\n if (\n AccessTokenEntity.isAccessTokenEntity(\n credObj\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - accessToken found, saving key to token key map\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - accessToken with key: ${key} found, saving key to token key map`\n );\n const accessTokenEntity =\n CacheManager.toObject(\n new AccessTokenEntity(),\n credObj\n );\n const newKey =\n this.updateCredentialCacheKey(\n key,\n accessTokenEntity\n );\n this.addTokenKey(\n newKey,\n CredentialType.ACCESS_TOKEN\n );\n return;\n } else {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - key found matching accessToken schema with value containing accessToken credentialType field but value failed AccessTokenEntity validation, skipping.\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - failed accessToken validation on key: ${key}`\n );\n }\n break;\n case CredentialType.REFRESH_TOKEN:\n if (\n RefreshTokenEntity.isRefreshTokenEntity(\n credObj\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - refreshToken found, saving key to token key map\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - refreshToken with key: ${key} found, saving key to token key map`\n );\n const refreshTokenEntity =\n CacheManager.toObject(\n new RefreshTokenEntity(),\n credObj\n );\n const newKey =\n this.updateCredentialCacheKey(\n key,\n refreshTokenEntity\n );\n this.addTokenKey(\n newKey,\n CredentialType.REFRESH_TOKEN\n );\n return;\n } else {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - key found matching refreshToken schema with value containing refreshToken credentialType field but value failed RefreshTokenEntity validation, skipping.\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - failed refreshToken validation on key: ${key}`\n );\n }\n break;\n default:\n // If credentialType isn't one of our predefined ones, it may not be an MSAL cache value. Ignore.\n }\n }\n }\n }\n\n if (this.isAccountKey(key)) {\n const value = this.getItem(key);\n if (value) {\n const accountObj = this.validateAndParseJson(value);\n if (\n accountObj &&\n AccountEntity.isAccountEntity(accountObj)\n ) {\n this.logger.trace(\n \"BrowserCacheManager:createKeyMaps - account found, saving key to account key map\"\n );\n this.logger.tracePii(\n `BrowserCacheManager:createKeyMaps - account with key: ${key} found, saving key to account key map`\n );\n this.addAccountKeyToMap(key);\n }\n }\n }\n });\n }\n\n /**\n * Parses passed value as JSON object, JSON.parse() will throw an error.\n * @param input\n */\n protected validateAndParseJson(jsonValue: string): object | null {\n try {\n const parsedJson = JSON.parse(jsonValue);\n /**\n * There are edge cases in which JSON.parse will successfully parse a non-valid JSON object\n * (e.g. JSON.parse will parse an escaped string into an unescaped string), so adding a type check\n * of the parsed value is necessary in order to be certain that the string represents a valid JSON object.\n *\n */\n return parsedJson && typeof parsedJson === \"object\"\n ? parsedJson\n : null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * fetches the entry from the browser storage based off the key\n * @param key\n */\n getItem(key: string): string | null {\n return this.browserStorage.getItem(key);\n }\n\n /**\n * sets the entry in the browser storage\n * @param key\n * @param value\n */\n setItem(key: string, value: string): void {\n this.browserStorage.setItem(key, value);\n }\n\n /**\n * fetch the account entity from the platform cache\n * @param accountKey\n */\n getAccount(accountKey: string): AccountEntity | null {\n this.logger.trace(\"BrowserCacheManager.getAccount called\");\n const account = this.getItem(accountKey);\n if (!account) {\n this.removeAccountKeyFromMap(accountKey);\n return null;\n }\n\n const parsedAccount = this.validateAndParseJson(account);\n if (!parsedAccount || !AccountEntity.isAccountEntity(parsedAccount)) {\n this.removeAccountKeyFromMap(accountKey);\n return null;\n }\n\n return CacheManager.toObject(\n new AccountEntity(),\n parsedAccount\n );\n }\n\n /**\n * set account entity in the platform cache\n * @param account\n */\n setAccount(account: AccountEntity): void {\n this.logger.trace(\"BrowserCacheManager.setAccount called\");\n const key = account.generateAccountKey();\n this.setItem(key, JSON.stringify(account));\n this.addAccountKeyToMap(key);\n }\n\n /**\n * Returns the array of account keys currently cached\n * @returns\n */\n getAccountKeys(): Array {\n this.logger.trace(\"BrowserCacheManager.getAccountKeys called\");\n const accountKeys = this.getItem(StaticCacheKeys.ACCOUNT_KEYS);\n if (accountKeys) {\n return JSON.parse(accountKeys);\n }\n\n this.logger.verbose(\n \"BrowserCacheManager.getAccountKeys - No account keys found\"\n );\n return [];\n }\n\n /**\n * Add a new account to the key map\n * @param key\n */\n addAccountKeyToMap(key: string): void {\n this.logger.trace(\"BrowserCacheManager.addAccountKeyToMap called\");\n this.logger.tracePii(\n `BrowserCacheManager.addAccountKeyToMap called with key: ${key}`\n );\n const accountKeys = this.getAccountKeys();\n if (accountKeys.indexOf(key) === -1) {\n // Only add key if it does not already exist in the map\n accountKeys.push(key);\n this.setItem(\n StaticCacheKeys.ACCOUNT_KEYS,\n JSON.stringify(accountKeys)\n );\n this.logger.verbose(\n \"BrowserCacheManager.addAccountKeyToMap account key added\"\n );\n } else {\n this.logger.verbose(\n \"BrowserCacheManager.addAccountKeyToMap account key already exists in map\"\n );\n }\n }\n\n /**\n * Remove an account from the key map\n * @param key\n */\n removeAccountKeyFromMap(key: string): void {\n this.logger.trace(\"BrowserCacheManager.removeAccountKeyFromMap called\");\n this.logger.tracePii(\n `BrowserCacheManager.removeAccountKeyFromMap called with key: ${key}`\n );\n const accountKeys = this.getAccountKeys();\n const removalIndex = accountKeys.indexOf(key);\n if (removalIndex > -1) {\n accountKeys.splice(removalIndex, 1);\n this.setItem(\n StaticCacheKeys.ACCOUNT_KEYS,\n JSON.stringify(accountKeys)\n );\n this.logger.trace(\n \"BrowserCacheManager.removeAccountKeyFromMap account key removed\"\n );\n } else {\n this.logger.trace(\n \"BrowserCacheManager.removeAccountKeyFromMap key not found in existing map\"\n );\n }\n }\n\n /**\n * Extends inherited removeAccount function to include removal of the account key from the map\n * @param key\n */\n async removeAccount(key: string): Promise {\n void super.removeAccount(key);\n this.removeAccountKeyFromMap(key);\n }\n\n /**\n * Removes given idToken from the cache and from the key map\n * @param key\n */\n removeIdToken(key: string): void {\n super.removeIdToken(key);\n this.removeTokenKey(key, CredentialType.ID_TOKEN);\n }\n\n /**\n * Removes given accessToken from the cache and from the key map\n * @param key\n */\n async removeAccessToken(key: string): Promise {\n void super.removeAccessToken(key);\n this.removeTokenKey(key, CredentialType.ACCESS_TOKEN);\n }\n\n /**\n * Removes given refreshToken from the cache and from the key map\n * @param key\n */\n removeRefreshToken(key: string): void {\n super.removeRefreshToken(key);\n this.removeTokenKey(key, CredentialType.REFRESH_TOKEN);\n }\n\n /**\n * Gets the keys for the cached tokens associated with this clientId\n * @returns\n */\n getTokenKeys(): TokenKeys {\n this.logger.trace(\"BrowserCacheManager.getTokenKeys called\");\n const item = this.getItem(\n `${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`\n );\n if (item) {\n const tokenKeys = this.validateAndParseJson(item);\n if (\n tokenKeys &&\n tokenKeys.hasOwnProperty(\"idToken\") &&\n tokenKeys.hasOwnProperty(\"accessToken\") &&\n tokenKeys.hasOwnProperty(\"refreshToken\")\n ) {\n return tokenKeys as TokenKeys;\n } else {\n this.logger.error(\n \"BrowserCacheManager.getTokenKeys - Token keys found but in an unknown format. Returning empty key map.\"\n );\n }\n } else {\n this.logger.verbose(\n \"BrowserCacheManager.getTokenKeys - No token keys found\"\n );\n }\n\n return {\n idToken: [],\n accessToken: [],\n refreshToken: [],\n };\n }\n\n /**\n * Adds the given key to the token key map\n * @param key\n * @param type\n */\n addTokenKey(key: string, type: CredentialType): void {\n this.logger.trace(\"BrowserCacheManager addTokenKey called\");\n const tokenKeys = this.getTokenKeys();\n\n switch (type) {\n case CredentialType.ID_TOKEN:\n if (tokenKeys.idToken.indexOf(key) === -1) {\n this.logger.info(\n \"BrowserCacheManager: addTokenKey - idToken added to map\"\n );\n tokenKeys.idToken.push(key);\n }\n break;\n case CredentialType.ACCESS_TOKEN:\n if (tokenKeys.accessToken.indexOf(key) === -1) {\n this.logger.info(\n \"BrowserCacheManager: addTokenKey - accessToken added to map\"\n );\n tokenKeys.accessToken.push(key);\n }\n break;\n case CredentialType.REFRESH_TOKEN:\n if (tokenKeys.refreshToken.indexOf(key) === -1) {\n this.logger.info(\n \"BrowserCacheManager: addTokenKey - refreshToken added to map\"\n );\n tokenKeys.refreshToken.push(key);\n }\n break;\n default:\n this.logger.error(\n `BrowserCacheManager:addTokenKey - CredentialType provided invalid. CredentialType: ${type}`\n );\n ClientAuthError.createUnexpectedCredentialTypeError();\n }\n\n this.setItem(\n `${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`,\n JSON.stringify(tokenKeys)\n );\n }\n\n /**\n * Removes the given key from the token key map\n * @param key\n * @param type\n */\n removeTokenKey(key: string, type: CredentialType): void {\n this.logger.trace(\"BrowserCacheManager removeTokenKey called\");\n const tokenKeys = this.getTokenKeys();\n\n switch (type) {\n case CredentialType.ID_TOKEN:\n this.logger.infoPii(\n `BrowserCacheManager: removeTokenKey - attempting to remove idToken with key: ${key} from map`\n );\n const idRemoval = tokenKeys.idToken.indexOf(key);\n if (idRemoval > -1) {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - idToken removed from map\"\n );\n tokenKeys.idToken.splice(idRemoval, 1);\n } else {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - idToken does not exist in map. Either it was previously removed or it was never added.\"\n );\n }\n break;\n case CredentialType.ACCESS_TOKEN:\n this.logger.infoPii(\n `BrowserCacheManager: removeTokenKey - attempting to remove accessToken with key: ${key} from map`\n );\n const accessRemoval = tokenKeys.accessToken.indexOf(key);\n if (accessRemoval > -1) {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - accessToken removed from map\"\n );\n tokenKeys.accessToken.splice(accessRemoval, 1);\n } else {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - accessToken does not exist in map. Either it was previously removed or it was never added.\"\n );\n }\n break;\n case CredentialType.REFRESH_TOKEN:\n this.logger.infoPii(\n `BrowserCacheManager: removeTokenKey - attempting to remove refreshToken with key: ${key} from map`\n );\n const refreshRemoval = tokenKeys.refreshToken.indexOf(key);\n if (refreshRemoval > -1) {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - refreshToken removed from map\"\n );\n tokenKeys.refreshToken.splice(refreshRemoval, 1);\n } else {\n this.logger.info(\n \"BrowserCacheManager: removeTokenKey - refreshToken does not exist in map. Either it was previously removed or it was never added.\"\n );\n }\n break;\n default:\n this.logger.error(\n `BrowserCacheManager:removeTokenKey - CredentialType provided invalid. CredentialType: ${type}`\n );\n ClientAuthError.createUnexpectedCredentialTypeError();\n }\n\n this.setItem(\n `${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`,\n JSON.stringify(tokenKeys)\n );\n }\n\n /**\n * generates idToken entity from a string\n * @param idTokenKey\n */\n getIdTokenCredential(idTokenKey: string): IdTokenEntity | null {\n const value = this.getItem(idTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(idTokenKey, CredentialType.ID_TOKEN);\n return null;\n }\n\n const parsedIdToken = this.validateAndParseJson(value);\n if (!parsedIdToken || !IdTokenEntity.isIdTokenEntity(parsedIdToken)) {\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(idTokenKey, CredentialType.ID_TOKEN);\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: cache hit\"\n );\n return CacheManager.toObject(new IdTokenEntity(), parsedIdToken);\n }\n\n /**\n * set IdToken credential to the platform cache\n * @param idToken\n */\n setIdTokenCredential(idToken: IdTokenEntity): void {\n this.logger.trace(\"BrowserCacheManager.setIdTokenCredential called\");\n const idTokenKey = idToken.generateCredentialKey();\n\n this.setItem(idTokenKey, JSON.stringify(idToken));\n\n this.addTokenKey(idTokenKey, CredentialType.ID_TOKEN);\n }\n\n /**\n * generates accessToken entity from a string\n * @param key\n */\n getAccessTokenCredential(accessTokenKey: string): AccessTokenEntity | null {\n const value = this.getItem(accessTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(accessTokenKey, CredentialType.ACCESS_TOKEN);\n return null;\n }\n const parsedAccessToken = this.validateAndParseJson(value);\n if (\n !parsedAccessToken ||\n !AccessTokenEntity.isAccessTokenEntity(parsedAccessToken)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(accessTokenKey, CredentialType.ACCESS_TOKEN);\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: cache hit\"\n );\n return CacheManager.toObject(\n new AccessTokenEntity(),\n parsedAccessToken\n );\n }\n\n /**\n * set accessToken credential to the platform cache\n * @param accessToken\n */\n setAccessTokenCredential(accessToken: AccessTokenEntity): void {\n this.logger.trace(\n \"BrowserCacheManager.setAccessTokenCredential called\"\n );\n const accessTokenKey = accessToken.generateCredentialKey();\n this.setItem(accessTokenKey, JSON.stringify(accessToken));\n\n this.addTokenKey(accessTokenKey, CredentialType.ACCESS_TOKEN);\n }\n\n /**\n * generates refreshToken entity from a string\n * @param refreshTokenKey\n */\n getRefreshTokenCredential(\n refreshTokenKey: string\n ): RefreshTokenEntity | null {\n const value = this.getItem(refreshTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(refreshTokenKey, CredentialType.REFRESH_TOKEN);\n return null;\n }\n const parsedRefreshToken = this.validateAndParseJson(value);\n if (\n !parsedRefreshToken ||\n !RefreshTokenEntity.isRefreshTokenEntity(parsedRefreshToken)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\n );\n this.removeTokenKey(refreshTokenKey, CredentialType.REFRESH_TOKEN);\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: cache hit\"\n );\n return CacheManager.toObject(\n new RefreshTokenEntity(),\n parsedRefreshToken\n );\n }\n\n /**\n * set refreshToken credential to the platform cache\n * @param refreshToken\n */\n setRefreshTokenCredential(refreshToken: RefreshTokenEntity): void {\n this.logger.trace(\n \"BrowserCacheManager.setRefreshTokenCredential called\"\n );\n const refreshTokenKey = refreshToken.generateCredentialKey();\n this.setItem(refreshTokenKey, JSON.stringify(refreshToken));\n\n this.addTokenKey(refreshTokenKey, CredentialType.REFRESH_TOKEN);\n }\n\n /**\n * fetch appMetadata entity from the platform cache\n * @param appMetadataKey\n */\n getAppMetadata(appMetadataKey: string): AppMetadataEntity | null {\n const value = this.getItem(appMetadataKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\n );\n return null;\n }\n\n const parsedMetadata = this.validateAndParseJson(value);\n if (\n !parsedMetadata ||\n !AppMetadataEntity.isAppMetadataEntity(\n appMetadataKey,\n parsedMetadata\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getAppMetadata: cache hit\");\n return CacheManager.toObject(new AppMetadataEntity(), parsedMetadata);\n }\n\n /**\n * set appMetadata entity to the platform cache\n * @param appMetadata\n */\n setAppMetadata(appMetadata: AppMetadataEntity): void {\n this.logger.trace(\"BrowserCacheManager.setAppMetadata called\");\n const appMetadataKey = appMetadata.generateAppMetadataKey();\n this.setItem(appMetadataKey, JSON.stringify(appMetadata));\n }\n\n /**\n * fetch server telemetry entity from the platform cache\n * @param serverTelemetryKey\n */\n getServerTelemetry(\n serverTelemetryKey: string\n ): ServerTelemetryEntity | null {\n const value = this.getItem(serverTelemetryKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\n );\n return null;\n }\n const parsedMetadata = this.validateAndParseJson(value);\n if (\n !parsedMetadata ||\n !ServerTelemetryEntity.isServerTelemetryEntity(\n serverTelemetryKey,\n parsedMetadata\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getServerTelemetry: cache hit\");\n return CacheManager.toObject(\n new ServerTelemetryEntity(),\n parsedMetadata\n );\n }\n\n /**\n * set server telemetry entity to the platform cache\n * @param serverTelemetryKey\n * @param serverTelemetry\n */\n setServerTelemetry(\n serverTelemetryKey: string,\n serverTelemetry: ServerTelemetryEntity\n ): void {\n this.logger.trace(\"BrowserCacheManager.setServerTelemetry called\");\n this.setItem(serverTelemetryKey, JSON.stringify(serverTelemetry));\n }\n\n /**\n *\n */\n getAuthorityMetadata(key: string): AuthorityMetadataEntity | null {\n const value = this.internalStorage.getItem(key);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAuthorityMetadata: called, no cache hit\"\n );\n return null;\n }\n const parsedMetadata = this.validateAndParseJson(value);\n if (\n parsedMetadata &&\n AuthorityMetadataEntity.isAuthorityMetadataEntity(\n key,\n parsedMetadata\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAuthorityMetadata: cache hit\"\n );\n return CacheManager.toObject(\n new AuthorityMetadataEntity(),\n parsedMetadata\n );\n }\n return null;\n }\n\n /**\n *\n */\n getAuthorityMetadataKeys(): Array {\n const allKeys = this.internalStorage.getKeys();\n return allKeys.filter((key) => {\n return this.isAuthorityMetadata(key);\n });\n }\n\n /**\n * Sets wrapper metadata in memory\n * @param wrapperSKU\n * @param wrapperVersion\n */\n setWrapperMetadata(wrapperSKU: string, wrapperVersion: string): void {\n this.internalStorage.setItem(InMemoryCacheKeys.WRAPPER_SKU, wrapperSKU);\n this.internalStorage.setItem(\n InMemoryCacheKeys.WRAPPER_VER,\n wrapperVersion\n );\n }\n\n /**\n * Returns wrapper metadata from in-memory storage\n */\n getWrapperMetadata(): [string, string] {\n const sku =\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_SKU) ||\n Constants.EMPTY_STRING;\n const version =\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_VER) ||\n Constants.EMPTY_STRING;\n return [sku, version];\n }\n\n /**\n *\n * @param entity\n */\n setAuthorityMetadata(key: string, entity: AuthorityMetadataEntity): void {\n this.logger.trace(\"BrowserCacheManager.setAuthorityMetadata called\");\n this.internalStorage.setItem(key, JSON.stringify(entity));\n }\n\n /**\n * Gets the active account\n */\n getActiveAccount(): AccountInfo | null {\n const activeAccountKeyFilters = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\n );\n const activeAccountValueFilters = this.getItem(activeAccountKeyFilters);\n if (!activeAccountValueFilters) {\n // if new active account cache type isn't found, it's an old version, so look for that instead\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: No active account filters cache schema found, looking for legacy schema\"\n );\n const activeAccountKeyLocal = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT\n );\n const activeAccountValueLocal = this.getItem(activeAccountKeyLocal);\n if (!activeAccountValueLocal) {\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: No active account found\"\n );\n return null;\n }\n const activeAccount =\n this.getAccountInfoByFilter({\n localAccountId: activeAccountValueLocal,\n })[0] || null;\n if (activeAccount) {\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: Legacy active account cache schema found\"\n );\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: Adding active account filters cache schema\"\n );\n this.setActiveAccount(activeAccount);\n return activeAccount;\n }\n return null;\n }\n const activeAccountValueObj = this.validateAndParseJson(\n activeAccountValueFilters\n ) as AccountInfo;\n if (activeAccountValueObj) {\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: Active account filters schema found\"\n );\n return (\n this.getAccountInfoByFilter({\n homeAccountId: activeAccountValueObj.homeAccountId,\n localAccountId: activeAccountValueObj.localAccountId,\n })[0] || null\n );\n }\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: No active account found\"\n );\n return null;\n }\n\n /**\n * Sets the active account's localAccountId in cache\n * @param account\n */\n setActiveAccount(account: AccountInfo | null): void {\n const activeAccountKey = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\n );\n const activeAccountKeyLocal = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT\n );\n if (account) {\n this.logger.verbose(\"setActiveAccount: Active account set\");\n const activeAccountValue: ActiveAccountFilters = {\n homeAccountId: account.homeAccountId,\n localAccountId: account.localAccountId,\n };\n this.browserStorage.setItem(\n activeAccountKey,\n JSON.stringify(activeAccountValue)\n );\n this.browserStorage.setItem(\n activeAccountKeyLocal,\n account.localAccountId\n );\n } else {\n this.logger.verbose(\n \"setActiveAccount: No account passed, active account not set\"\n );\n this.browserStorage.removeItem(activeAccountKey);\n this.browserStorage.removeItem(activeAccountKeyLocal);\n }\n }\n\n /**\n * Gets a list of accounts that match all of the filters provided\n * @param account\n */\n getAccountInfoByFilter(\n accountFilter: Partial>\n ): AccountInfo[] {\n const allAccounts = this.getAllAccounts();\n this.logger.trace(\n `BrowserCacheManager.getAccountInfoByFilter: total ${allAccounts.length} accounts found`\n );\n\n return allAccounts.filter((accountObj) => {\n if (\n accountFilter.username &&\n accountFilter.username.toLowerCase() !==\n accountObj.username.toLowerCase()\n ) {\n return false;\n }\n\n if (\n accountFilter.homeAccountId &&\n accountFilter.homeAccountId !== accountObj.homeAccountId\n ) {\n return false;\n }\n\n if (\n accountFilter.localAccountId &&\n accountFilter.localAccountId !== accountObj.localAccountId\n ) {\n return false;\n }\n\n if (\n accountFilter.tenantId &&\n accountFilter.tenantId !== accountObj.tenantId\n ) {\n return false;\n }\n\n if (\n accountFilter.environment &&\n accountFilter.environment !== accountObj.environment\n ) {\n return false;\n }\n\n return true;\n });\n }\n\n /**\n * Checks the cache for accounts matching loginHint or SID\n * @param loginHint\n * @param sid\n */\n getAccountInfoByHints(\n loginHint?: string,\n sid?: string\n ): AccountInfo | null {\n const matchingAccounts = this.getAllAccounts().filter((accountInfo) => {\n if (sid) {\n const accountSid =\n accountInfo.idTokenClaims &&\n accountInfo.idTokenClaims[\"sid\"];\n return sid === accountSid;\n }\n\n if (loginHint) {\n return loginHint === accountInfo.username;\n }\n\n return false;\n });\n\n if (matchingAccounts.length === 1) {\n return matchingAccounts[0];\n } else if (matchingAccounts.length > 1) {\n throw ClientAuthError.createMultipleMatchingAccountsInCacheError();\n }\n\n return null;\n }\n\n /**\n * fetch throttling entity from the platform cache\n * @param throttlingCacheKey\n */\n getThrottlingCache(throttlingCacheKey: string): ThrottlingEntity | null {\n const value = this.getItem(throttlingCacheKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\n );\n return null;\n }\n\n const parsedThrottlingCache = this.validateAndParseJson(value);\n if (\n !parsedThrottlingCache ||\n !ThrottlingEntity.isThrottlingEntity(\n throttlingCacheKey,\n parsedThrottlingCache\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getThrottlingCache: cache hit\");\n return CacheManager.toObject(\n new ThrottlingEntity(),\n parsedThrottlingCache\n );\n }\n\n /**\n * set throttling entity to the platform cache\n * @param throttlingCacheKey\n * @param throttlingCache\n */\n setThrottlingCache(\n throttlingCacheKey: string,\n throttlingCache: ThrottlingEntity\n ): void {\n this.logger.trace(\"BrowserCacheManager.setThrottlingCache called\");\n this.setItem(throttlingCacheKey, JSON.stringify(throttlingCache));\n }\n\n /**\n * Gets cache item with given key.\n * Will retrieve from cookies if storeAuthStateInCookie is set to true.\n * @param key\n */\n getTemporaryCache(cacheKey: string, generateKey?: boolean): string | null {\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\n if (this.cacheConfig.storeAuthStateInCookie) {\n const itemCookie = this.getItemCookie(key);\n if (itemCookie) {\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: storeAuthStateInCookies set to true, retrieving from cookies\"\n );\n return itemCookie;\n }\n }\n\n const value = this.temporaryCacheStorage.getItem(key);\n if (!value) {\n // If temp cache item not found in session/memory, check local storage for items set by old versions\n if (\n this.cacheConfig.cacheLocation ===\n BrowserCacheLocation.LocalStorage\n ) {\n const item = this.browserStorage.getItem(key);\n if (item) {\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item found in local storage\"\n );\n return item;\n }\n }\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: No cache item found in local storage\"\n );\n return null;\n }\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item returned\"\n );\n return value;\n }\n\n /**\n * Sets the cache item with the key and value given.\n * Stores in cookie if storeAuthStateInCookie is set to true.\n * This can cause cookie overflow if used incorrectly.\n * @param key\n * @param value\n */\n setTemporaryCache(\n cacheKey: string,\n value: string,\n generateKey?: boolean\n ): void {\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\n\n this.temporaryCacheStorage.setItem(key, value);\n if (this.cacheConfig.storeAuthStateInCookie) {\n this.logger.trace(\n \"BrowserCacheManager.setTemporaryCache: storeAuthStateInCookie set to true, setting item cookie\"\n );\n this.setItemCookie(key, value);\n }\n }\n\n /**\n * Removes the cache item with the given key.\n * Will also clear the cookie item if storeAuthStateInCookie is set to true.\n * @param key\n */\n removeItem(key: string): void {\n this.browserStorage.removeItem(key);\n this.temporaryCacheStorage.removeItem(key);\n if (this.cacheConfig.storeAuthStateInCookie) {\n this.logger.trace(\n \"BrowserCacheManager.removeItem: storeAuthStateInCookie is true, clearing item cookie\"\n );\n this.clearItemCookie(key);\n }\n }\n\n /**\n * Checks whether key is in cache.\n * @param key\n */\n containsKey(key: string): boolean {\n return (\n this.browserStorage.containsKey(key) ||\n this.temporaryCacheStorage.containsKey(key)\n );\n }\n\n /**\n * Gets all keys in window.\n */\n getKeys(): string[] {\n return [\n ...this.browserStorage.getKeys(),\n ...this.temporaryCacheStorage.getKeys(),\n ];\n }\n\n /**\n * Clears all cache entries created by MSAL.\n */\n async clear(): Promise {\n // Removes all accounts and their credentials\n await this.removeAllAccounts();\n this.removeAppMetadata();\n\n // Removes all remaining MSAL cache items\n this.getKeys().forEach((cacheKey: string) => {\n // Check if key contains msal prefix; For now, we are clearing all the cache items created by MSAL.js\n if (\n (this.browserStorage.containsKey(cacheKey) ||\n this.temporaryCacheStorage.containsKey(cacheKey)) &&\n (cacheKey.indexOf(Constants.CACHE_PREFIX) !== -1 ||\n cacheKey.indexOf(this.clientId) !== -1)\n ) {\n this.removeItem(cacheKey);\n }\n });\n\n this.internalStorage.clear();\n }\n\n /**\n * Clears all access tokes that have claims prior to saving the current one\n * @param credential\n * @returns\n */\n async clearTokensAndKeysWithClaims(): Promise {\n const tokenKeys = this.getTokenKeys();\n\n const removedAccessTokens: Array> = [];\n tokenKeys.accessToken.forEach((key: string) => {\n // if the access token has claims in its key, remove the token key and the token\n const credential = this.getAccessTokenCredential(key);\n if (\n credential?.requestedClaimsHash &&\n key.includes(credential.requestedClaimsHash.toLowerCase())\n ) {\n removedAccessTokens.push(this.removeAccessToken(key));\n }\n });\n await Promise.all(removedAccessTokens);\n\n // warn if any access tokens are removed\n if (removedAccessTokens.length > 0) {\n this.logger.warning(\n `${removedAccessTokens.length} access tokens with claims in the cache keys have been removed from the cache.`\n );\n }\n }\n\n /**\n * Add value to cookies\n * @param cookieName\n * @param cookieValue\n * @param expires\n */\n setItemCookie(\n cookieName: string,\n cookieValue: string,\n expires?: number\n ): void {\n let cookieStr = `${encodeURIComponent(cookieName)}=${encodeURIComponent(\n cookieValue\n )};path=/;SameSite=Lax;`;\n if (expires) {\n const expireTime = this.getCookieExpirationTime(expires);\n cookieStr += `expires=${expireTime};`;\n }\n\n if (this.cacheConfig.secureCookies) {\n cookieStr += \"Secure;\";\n }\n\n document.cookie = cookieStr;\n }\n\n /**\n * Get one item by key from cookies\n * @param cookieName\n */\n getItemCookie(cookieName: string): string {\n const name = `${encodeURIComponent(cookieName)}=`;\n const cookieList = document.cookie.split(\";\");\n for (let i: number = 0; i < cookieList.length; i++) {\n let cookie = cookieList[i];\n while (cookie.charAt(0) === \" \") {\n cookie = cookie.substring(1);\n }\n if (cookie.indexOf(name) === 0) {\n return decodeURIComponent(\n cookie.substring(name.length, cookie.length)\n );\n }\n }\n return Constants.EMPTY_STRING;\n }\n\n /**\n * Clear all msal-related cookies currently set in the browser. Should only be used to clear temporary cache items.\n */\n clearMsalCookies(): void {\n const cookiePrefix = `${Constants.CACHE_PREFIX}.${this.clientId}`;\n const cookieList = document.cookie.split(\";\");\n cookieList.forEach((cookie: string): void => {\n while (cookie.charAt(0) === \" \") {\n // eslint-disable-next-line no-param-reassign\n cookie = cookie.substring(1);\n }\n if (cookie.indexOf(cookiePrefix) === 0) {\n const cookieKey = cookie.split(\"=\")[0];\n this.clearItemCookie(cookieKey);\n }\n });\n }\n\n /**\n * Clear an item in the cookies by key\n * @param cookieName\n */\n clearItemCookie(cookieName: string): void {\n this.setItemCookie(cookieName, Constants.EMPTY_STRING, -1);\n }\n\n /**\n * Get cookie expiration time\n * @param cookieLifeDays\n */\n getCookieExpirationTime(cookieLifeDays: number): string {\n const today = new Date();\n const expr = new Date(\n today.getTime() + cookieLifeDays * this.COOKIE_LIFE_MULTIPLIER\n );\n return expr.toUTCString();\n }\n\n /**\n * Gets the cache object referenced by the browser\n */\n getCache(): object {\n return this.browserStorage;\n }\n\n /**\n * interface compat, we cannot overwrite browser cache; Functionality is supported by individual entities in browser\n */\n setCache(): void {\n // sets nothing\n }\n\n /**\n * Prepend msal. to each key; Skip for any JSON object as Key (defined schemas do not need the key appended: AccessToken Keys or the upcoming schema)\n * @param key\n * @param addInstanceId\n */\n generateCacheKey(key: string): string {\n const generatedKey = this.validateAndParseJson(key);\n if (!generatedKey) {\n if (\n StringUtils.startsWith(key, Constants.CACHE_PREFIX) ||\n StringUtils.startsWith(key, PersistentCacheKeys.ADAL_ID_TOKEN)\n ) {\n return key;\n }\n return `${Constants.CACHE_PREFIX}.${this.clientId}.${key}`;\n }\n\n return JSON.stringify(key);\n }\n\n /**\n * Create authorityKey to cache authority\n * @param state\n */\n generateAuthorityKey(stateString: string): string {\n const {\n libraryState: { id: stateId },\n } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);\n\n return this.generateCacheKey(\n `${TemporaryCacheKeys.AUTHORITY}.${stateId}`\n );\n }\n\n /**\n * Create Nonce key to cache nonce\n * @param state\n */\n generateNonceKey(stateString: string): string {\n const {\n libraryState: { id: stateId },\n } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);\n\n return this.generateCacheKey(\n `${TemporaryCacheKeys.NONCE_IDTOKEN}.${stateId}`\n );\n }\n\n /**\n * Creates full cache key for the request state\n * @param stateString State string for the request\n */\n generateStateKey(stateString: string): string {\n // Use the library state id to key temp storage for uniqueness for multiple concurrent requests\n const {\n libraryState: { id: stateId },\n } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);\n return this.generateCacheKey(\n `${TemporaryCacheKeys.REQUEST_STATE}.${stateId}`\n );\n }\n\n /**\n * Gets the cached authority based on the cached state. Returns empty if no cached state found.\n */\n getCachedAuthority(cachedState: string): string | null {\n const stateCacheKey = this.generateStateKey(cachedState);\n const state = this.getTemporaryCache(stateCacheKey);\n if (!state) {\n return null;\n }\n\n const authorityCacheKey = this.generateAuthorityKey(state);\n return this.getTemporaryCache(authorityCacheKey);\n }\n\n /**\n * Updates account, authority, and state in cache\n * @param serverAuthenticationRequest\n * @param account\n */\n updateCacheEntries(\n state: string,\n nonce: string,\n authorityInstance: string,\n loginHint: string,\n account: AccountInfo | null\n ): void {\n this.logger.trace(\"BrowserCacheManager.updateCacheEntries called\");\n // Cache the request state\n const stateCacheKey = this.generateStateKey(state);\n this.setTemporaryCache(stateCacheKey, state, false);\n\n // Cache the nonce\n const nonceCacheKey = this.generateNonceKey(state);\n this.setTemporaryCache(nonceCacheKey, nonce, false);\n\n // Cache authorityKey\n const authorityCacheKey = this.generateAuthorityKey(state);\n this.setTemporaryCache(authorityCacheKey, authorityInstance, false);\n\n if (account) {\n const ccsCredential: CcsCredential = {\n credential: account.homeAccountId,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n this.setTemporaryCache(\n TemporaryCacheKeys.CCS_CREDENTIAL,\n JSON.stringify(ccsCredential),\n true\n );\n } else if (loginHint) {\n const ccsCredential: CcsCredential = {\n credential: loginHint,\n type: CcsCredentialType.UPN,\n };\n this.setTemporaryCache(\n TemporaryCacheKeys.CCS_CREDENTIAL,\n JSON.stringify(ccsCredential),\n true\n );\n }\n }\n\n /**\n * Reset all temporary cache items\n * @param state\n */\n resetRequestCache(state: string): void {\n this.logger.trace(\"BrowserCacheManager.resetRequestCache called\");\n // check state and remove associated cache items\n if (state) {\n this.getKeys().forEach((key) => {\n if (key.indexOf(state) !== -1) {\n this.removeItem(key);\n }\n });\n\n // delete generic interactive request parameters\n this.removeItem(this.generateStateKey(state));\n this.removeItem(this.generateNonceKey(state));\n this.removeItem(this.generateAuthorityKey(state));\n }\n this.removeItem(\n this.generateCacheKey(TemporaryCacheKeys.REQUEST_PARAMS)\n );\n this.removeItem(this.generateCacheKey(TemporaryCacheKeys.ORIGIN_URI));\n this.removeItem(this.generateCacheKey(TemporaryCacheKeys.URL_HASH));\n this.removeItem(\n this.generateCacheKey(TemporaryCacheKeys.CORRELATION_ID)\n );\n this.removeItem(\n this.generateCacheKey(TemporaryCacheKeys.CCS_CREDENTIAL)\n );\n this.removeItem(\n this.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST)\n );\n this.setInteractionInProgress(false);\n }\n\n /**\n * Removes temporary cache for the provided state\n * @param stateString\n */\n cleanRequestByState(stateString: string): void {\n this.logger.trace(\"BrowserCacheManager.cleanRequestByState called\");\n // Interaction is completed - remove interaction status.\n if (stateString) {\n const stateKey = this.generateStateKey(stateString);\n const cachedState = this.temporaryCacheStorage.getItem(stateKey);\n this.logger.infoPii(\n `BrowserCacheManager.cleanRequestByState: Removing temporary cache items for state: ${cachedState}`\n );\n this.resetRequestCache(cachedState || Constants.EMPTY_STRING);\n }\n this.clearMsalCookies();\n }\n\n /**\n * Looks in temporary cache for any state values with the provided interactionType and removes all temporary cache items for that state\n * Used in scenarios where temp cache needs to be cleaned but state is not known, such as clicking browser back button.\n * @param interactionType\n */\n cleanRequestByInteractionType(interactionType: InteractionType): void {\n this.logger.trace(\n \"BrowserCacheManager.cleanRequestByInteractionType called\"\n );\n // Loop through all keys to find state key\n this.getKeys().forEach((key) => {\n // If this key is not the state key, move on\n if (key.indexOf(TemporaryCacheKeys.REQUEST_STATE) === -1) {\n return;\n }\n\n // Retrieve state value, return if not a valid value\n const stateValue = this.temporaryCacheStorage.getItem(key);\n if (!stateValue) {\n return;\n }\n // Extract state and ensure it matches given InteractionType, then clean request cache\n const parsedState = BrowserProtocolUtils.extractBrowserRequestState(\n this.cryptoImpl,\n stateValue\n );\n if (\n parsedState &&\n parsedState.interactionType === interactionType\n ) {\n this.logger.infoPii(\n `BrowserCacheManager.cleanRequestByInteractionType: Removing temporary cache items for state: ${stateValue}`\n );\n this.resetRequestCache(stateValue);\n }\n });\n this.clearMsalCookies();\n this.setInteractionInProgress(false);\n }\n\n cacheCodeRequest(authCodeRequest: CommonAuthorizationCodeRequest): void {\n this.logger.trace(\"BrowserCacheManager.cacheCodeRequest called\");\n\n const encodedValue = base64Encode(JSON.stringify(authCodeRequest));\n this.setTemporaryCache(\n TemporaryCacheKeys.REQUEST_PARAMS,\n encodedValue,\n true\n );\n }\n\n /**\n * Gets the token exchange parameters from the cache. Throws an error if nothing is found.\n */\n getCachedRequest(state: string): CommonAuthorizationCodeRequest {\n this.logger.trace(\"BrowserCacheManager.getCachedRequest called\");\n // Get token request from cache and parse as TokenExchangeParameters.\n const encodedTokenRequest = this.getTemporaryCache(\n TemporaryCacheKeys.REQUEST_PARAMS,\n true\n );\n if (!encodedTokenRequest) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.noTokenRequestCacheError\n );\n }\n\n let parsedRequest: CommonAuthorizationCodeRequest;\n try {\n parsedRequest = JSON.parse(base64Decode(encodedTokenRequest));\n } catch (e) {\n this.logger.errorPii(`Attempted to parse: ${encodedTokenRequest}`);\n this.logger.error(\n `Parsing cached token request threw with error: ${e}`\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.unableToParseTokenRequestCacheError\n );\n }\n this.removeItem(\n this.generateCacheKey(TemporaryCacheKeys.REQUEST_PARAMS)\n );\n\n // Get cached authority and use if no authority is cached with request.\n if (!parsedRequest.authority) {\n const authorityCacheKey: string = this.generateAuthorityKey(state);\n const cachedAuthority = this.getTemporaryCache(authorityCacheKey);\n if (!cachedAuthority) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.noCachedAuthorityError\n );\n }\n parsedRequest.authority = cachedAuthority;\n }\n\n return parsedRequest;\n }\n\n /**\n * Gets cached native request for redirect flows\n */\n getCachedNativeRequest(): NativeTokenRequest | null {\n this.logger.trace(\"BrowserCacheManager.getCachedNativeRequest called\");\n const cachedRequest = this.getTemporaryCache(\n TemporaryCacheKeys.NATIVE_REQUEST,\n true\n );\n if (!cachedRequest) {\n this.logger.trace(\n \"BrowserCacheManager.getCachedNativeRequest: No cached native request found\"\n );\n return null;\n }\n\n const parsedRequest = this.validateAndParseJson(\n cachedRequest\n ) as NativeTokenRequest;\n if (!parsedRequest) {\n this.logger.error(\n \"BrowserCacheManager.getCachedNativeRequest: Unable to parse native request\"\n );\n return null;\n }\n\n return parsedRequest;\n }\n\n isInteractionInProgress(matchClientId?: boolean): boolean {\n const clientId = this.getInteractionInProgress();\n\n if (matchClientId) {\n return clientId === this.clientId;\n } else {\n return !!clientId;\n }\n }\n\n getInteractionInProgress(): string | null {\n const key = `${Constants.CACHE_PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\n return this.getTemporaryCache(key, false);\n }\n\n setInteractionInProgress(inProgress: boolean): void {\n // Ensure we don't overwrite interaction in progress for a different clientId\n const key = `${Constants.CACHE_PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\n if (inProgress) {\n if (this.getInteractionInProgress()) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.interactionInProgress\n );\n } else {\n // No interaction is in progress\n this.setTemporaryCache(key, this.clientId, false);\n }\n } else if (\n !inProgress &&\n this.getInteractionInProgress() === this.clientId\n ) {\n this.removeItem(key);\n }\n }\n\n /**\n * Returns username retrieved from ADAL or MSAL v1 idToken\n * @deprecated\n */\n getLegacyLoginHint(): string | null {\n // Only check for adal/msal token if no SSO params are being used\n const adalIdTokenString = this.getTemporaryCache(\n PersistentCacheKeys.ADAL_ID_TOKEN\n );\n if (adalIdTokenString) {\n this.browserStorage.removeItem(PersistentCacheKeys.ADAL_ID_TOKEN);\n this.logger.verbose(\"Cached ADAL id token retrieved.\");\n }\n\n // Check for cached MSAL v1 id token\n const msalIdTokenString = this.getTemporaryCache(\n PersistentCacheKeys.ID_TOKEN,\n true\n );\n if (msalIdTokenString) {\n this.removeItem(\n this.generateCacheKey(PersistentCacheKeys.ID_TOKEN)\n );\n this.logger.verbose(\"Cached MSAL.js v1 id token retrieved\");\n }\n\n const cachedIdTokenString = msalIdTokenString || adalIdTokenString;\n if (cachedIdTokenString) {\n const idTokenClaims = AuthToken.extractTokenClaims(\n cachedIdTokenString,\n base64Decode\n );\n if (idTokenClaims.preferred_username) {\n this.logger.verbose(\n \"No SSO params used and ADAL/MSAL v1 token retrieved, setting ADAL/MSAL v1 preferred_username as loginHint\"\n );\n return idTokenClaims.preferred_username;\n } else if (idTokenClaims.upn) {\n this.logger.verbose(\n \"No SSO params used and ADAL/MSAL v1 token retrieved, setting ADAL/MSAL v1 upn as loginHint\"\n );\n return idTokenClaims.upn;\n } else {\n this.logger.verbose(\n \"No SSO params used and ADAL/MSAL v1 token retrieved, however, no account hint claim found. Enable preferred_username or upn id token claim to get SSO.\"\n );\n }\n }\n\n return null;\n }\n\n /**\n * Updates a credential's cache key if the current cache key is outdated\n */\n updateCredentialCacheKey(\n currentCacheKey: string,\n credential: ValidCredentialType\n ): string {\n const updatedCacheKey = credential.generateCredentialKey();\n\n if (currentCacheKey !== updatedCacheKey) {\n const cacheItem = this.getItem(currentCacheKey);\n if (cacheItem) {\n this.removeItem(currentCacheKey);\n this.setItem(updatedCacheKey, cacheItem);\n this.logger.verbose(\n `Updated an outdated ${credential.credentialType} cache key`\n );\n return updatedCacheKey;\n } else {\n this.logger.error(\n `Attempted to update an outdated ${credential.credentialType} cache key but no item matching the outdated key was found in storage`\n );\n }\n }\n\n return currentCacheKey;\n }\n\n /**\n * Returns application id as redirect context during AcquireTokenRedirect flow.\n */\n getRedirectRequestContext(): string | null {\n return this.getTemporaryCache(\n TemporaryCacheKeys.REDIRECT_CONTEXT,\n true\n );\n }\n\n /**\n * Sets application id as the redirect context during AcquireTokenRedirect flow.\n * @param value\n */\n setRedirectRequestContext(value: string): void {\n this.setTemporaryCache(\n TemporaryCacheKeys.REDIRECT_CONTEXT,\n value,\n true\n );\n }\n\n /**\n * Builds credential entities from AuthenticationResult object and saves the resulting credentials to the cache\n * @param result\n * @param request\n */\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n const idTokenEntity = IdTokenEntity.createIdTokenEntity(\n result.account?.homeAccountId,\n result.account?.environment,\n result.idToken,\n this.clientId,\n result.tenantId\n );\n\n let claimsHash;\n if (request.claims) {\n claimsHash = await this.cryptoImpl.hashString(request.claims);\n }\n const accessTokenEntity = AccessTokenEntity.createAccessTokenEntity(\n result.account?.homeAccountId,\n result.account.environment,\n result.accessToken,\n this.clientId,\n result.tenantId,\n result.scopes.join(\" \"),\n result.expiresOn?.getTime() || 0,\n result.extExpiresOn?.getTime() || 0,\n this.cryptoImpl,\n undefined, // refreshOn\n result.tokenType as AuthenticationScheme,\n undefined, // userAssertionHash\n request.sshKid,\n request.claims,\n claimsHash\n );\n\n const cacheRecord = new CacheRecord(\n undefined,\n idTokenEntity,\n accessTokenEntity\n );\n return this.saveCacheRecord(cacheRecord);\n }\n}\n\nexport const DEFAULT_BROWSER_CACHE_MANAGER = (\n clientId: string,\n logger: Logger\n): BrowserCacheManager => {\n const cacheOptions: Required = {\n cacheLocation: BrowserCacheLocation.MemoryStorage,\n temporaryCacheLocation: BrowserCacheLocation.MemoryStorage,\n storeAuthStateInCookie: false,\n secureCookies: false,\n cacheMigrationEnabled: false,\n claimsBasedCachingEnabled: false,\n };\n return new BrowserCacheManager(\n clientId,\n cacheOptions,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n logger\n );\n};\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants, UrlString } from \"@azure/msal-common\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError\";\nimport { InteractionType, BrowserConstants } from \"./BrowserConstants\";\n\n/**\n * Utility class for browser specific functions\n */\nexport class BrowserUtils {\n // #region Window Navigation and URL management\n\n /**\n * Clears hash from window url.\n */\n static clearHash(contentWindow: Window): void {\n // Office.js sets history.replaceState to null\n contentWindow.location.hash = Constants.EMPTY_STRING;\n if (typeof contentWindow.history.replaceState === \"function\") {\n // Full removes \"#\" from url\n contentWindow.history.replaceState(\n null,\n Constants.EMPTY_STRING,\n `${contentWindow.location.origin}${contentWindow.location.pathname}${contentWindow.location.search}`\n );\n }\n }\n\n /**\n * Replaces current hash with hash from provided url\n */\n static replaceHash(url: string): void {\n const urlParts = url.split(\"#\");\n urlParts.shift(); // Remove part before the hash\n window.location.hash =\n urlParts.length > 0 ? urlParts.join(\"#\") : Constants.EMPTY_STRING;\n }\n\n /**\n * Returns boolean of whether the current window is in an iframe or not.\n */\n static isInIframe(): boolean {\n return window.parent !== window;\n }\n\n /**\n * Returns boolean of whether or not the current window is a popup opened by msal\n */\n static isInPopup(): boolean {\n return (\n typeof window !== \"undefined\" &&\n !!window.opener &&\n window.opener !== window &&\n typeof window.name === \"string\" &&\n window.name.indexOf(`${BrowserConstants.POPUP_NAME_PREFIX}.`) === 0\n );\n }\n\n // #endregion\n\n /**\n * Returns current window URL as redirect uri\n */\n static getCurrentUri(): string {\n return window.location.href.split(\"?\")[0].split(\"#\")[0];\n }\n\n /**\n * Gets the homepage url for the current window location.\n */\n static getHomepage(): string {\n const currentUrl = new UrlString(window.location.href);\n const urlComponents = currentUrl.getUrlComponents();\n return `${urlComponents.Protocol}//${urlComponents.HostNameAndPort}/`;\n }\n\n /**\n * Throws error if we have completed an auth and are\n * attempting another auth request inside an iframe.\n */\n static blockReloadInHiddenIframes(): void {\n const isResponseHash = UrlString.hashContainsKnownProperties(\n window.location.hash\n );\n // return an error if called from the hidden iframe created by the msal js silent calls\n if (isResponseHash && BrowserUtils.isInIframe()) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.blockIframeReload\n );\n }\n }\n\n /**\n * Block redirect operations in iframes unless explicitly allowed\n * @param interactionType Interaction type for the request\n * @param allowRedirectInIframe Config value to allow redirects when app is inside an iframe\n */\n static blockRedirectInIframe(\n interactionType: InteractionType,\n allowRedirectInIframe: boolean\n ): void {\n const isIframedApp = BrowserUtils.isInIframe();\n if (\n interactionType === InteractionType.Redirect &&\n isIframedApp &&\n !allowRedirectInIframe\n ) {\n // If we are not in top frame, we shouldn't redirect. This is also handled by the service.\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.redirectInIframe\n );\n }\n }\n\n /**\n * Block redirectUri loaded in popup from calling AcquireToken APIs\n */\n static blockAcquireTokenInPopups(): void {\n // Popups opened by msal popup APIs are given a name that starts with \"msal.\"\n if (BrowserUtils.isInPopup()) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.blockNestedPopups\n );\n }\n }\n\n /**\n * Throws error if token requests are made in non-browser environment\n * @param isBrowserEnvironment Flag indicating if environment is a browser.\n */\n static blockNonBrowserEnvironment(isBrowserEnvironment: boolean): void {\n if (!isBrowserEnvironment) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nonBrowserEnvironment\n );\n }\n }\n\n /**\n * Throws error if initialize hasn't been called\n * @param initialized\n */\n static blockAPICallsBeforeInitialize(initialized: boolean): void {\n if (!initialized) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n );\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n Logger,\n AccountEntity,\n CacheManager,\n} from \"@azure/msal-common\";\nimport { InteractionType } from \"../utils/BrowserConstants\";\nimport {\n EventCallbackFunction,\n EventError,\n EventMessage,\n EventPayload,\n} from \"./EventMessage\";\nimport { EventType } from \"./EventType\";\n\nexport class EventHandler {\n // Callback for subscribing to events\n private eventCallbacks: Map;\n private logger: Logger;\n private browserCrypto: ICrypto;\n private listeningToStorageEvents: boolean;\n\n constructor(logger: Logger, browserCrypto: ICrypto) {\n this.eventCallbacks = new Map();\n this.logger = logger;\n this.browserCrypto = browserCrypto;\n this.listeningToStorageEvents = false;\n this.handleAccountCacheChange =\n this.handleAccountCacheChange.bind(this);\n }\n\n /**\n * Adds event callbacks to array\n * @param callback\n */\n addEventCallback(callback: EventCallbackFunction): string | null {\n if (typeof window !== \"undefined\") {\n const callbackId = this.browserCrypto.createNewGuid();\n this.eventCallbacks.set(callbackId, callback);\n this.logger.verbose(\n `Event callback registered with id: ${callbackId}`\n );\n\n return callbackId;\n }\n\n return null;\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n this.eventCallbacks.delete(callbackId);\n this.logger.verbose(`Event callback ${callbackId} removed.`);\n }\n\n /**\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n enableAccountStorageEvents(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (!this.listeningToStorageEvents) {\n this.logger.verbose(\"Adding account storage listener.\");\n this.listeningToStorageEvents = true;\n window.addEventListener(\"storage\", this.handleAccountCacheChange);\n } else {\n this.logger.verbose(\"Account storage listener already registered.\");\n }\n }\n\n /**\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n disableAccountStorageEvents(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (this.listeningToStorageEvents) {\n this.logger.verbose(\"Removing account storage listener.\");\n window.removeEventListener(\n \"storage\",\n this.handleAccountCacheChange\n );\n this.listeningToStorageEvents = false;\n } else {\n this.logger.verbose(\"No account storage listener registered.\");\n }\n }\n\n /**\n * Emits events by calling callback with event message\n * @param eventType\n * @param interactionType\n * @param payload\n * @param error\n */\n emitEvent(\n eventType: EventType,\n interactionType?: InteractionType,\n payload?: EventPayload,\n error?: EventError\n ): void {\n if (typeof window !== \"undefined\") {\n const message: EventMessage = {\n eventType: eventType,\n interactionType: interactionType || null,\n payload: payload || null,\n error: error || null,\n timestamp: Date.now(),\n };\n\n this.logger.info(`Emitting event: ${eventType}`);\n\n this.eventCallbacks.forEach(\n (callback: EventCallbackFunction, callbackId: string) => {\n this.logger.verbose(\n `Emitting event to callback ${callbackId}: ${eventType}`\n );\n callback.apply(null, [message]);\n }\n );\n }\n }\n\n /**\n * Emit account added/removed events when cached accounts are changed in a different tab or frame\n */\n private handleAccountCacheChange(e: StorageEvent): void {\n try {\n const cacheValue = e.newValue || e.oldValue;\n if (!cacheValue) {\n return;\n }\n const parsedValue = JSON.parse(cacheValue);\n if (\n typeof parsedValue !== \"object\" ||\n !AccountEntity.isAccountEntity(parsedValue)\n ) {\n return;\n }\n const accountEntity = CacheManager.toObject(\n new AccountEntity(),\n parsedValue\n );\n const accountInfo = accountEntity.getAccountInfo();\n if (!e.oldValue && e.newValue) {\n this.logger.info(\n \"Account was added to cache in a different window\"\n );\n this.emitEvent(EventType.ACCOUNT_ADDED, undefined, accountInfo);\n } else if (!e.newValue && e.oldValue) {\n this.logger.info(\n \"Account was removed from cache in a different window\"\n );\n this.emitEvent(\n EventType.ACCOUNT_REMOVED,\n undefined,\n accountInfo\n );\n }\n } catch (e) {\n return;\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { NetworkResponse } from \"./NetworkManager\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse\";\nimport {\n HeaderNames,\n ThrottlingConstants,\n Constants,\n} from \"../utils/Constants\";\nimport { CacheManager } from \"../cache/CacheManager\";\nimport { ServerError } from \"../error/ServerError\";\nimport { RequestThumbprint } from \"./RequestThumbprint\";\nimport { ThrottlingEntity } from \"../cache/entities/ThrottlingEntity\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest\";\n\n/** @internal */\nexport class ThrottlingUtils {\n /**\n * Prepares a RequestThumbprint to be stored as a key.\n * @param thumbprint\n */\n static generateThrottlingStorageKey(thumbprint: RequestThumbprint): string {\n return `${ThrottlingConstants.THROTTLING_PREFIX}.${JSON.stringify(\n thumbprint\n )}`;\n }\n\n /**\n * Performs necessary throttling checks before a network request.\n * @param cacheManager\n * @param thumbprint\n */\n static preProcess(\n cacheManager: CacheManager,\n thumbprint: RequestThumbprint\n ): void {\n const key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint);\n const value = cacheManager.getThrottlingCache(key);\n\n if (value) {\n if (value.throttleTime < Date.now()) {\n cacheManager.removeItem(key);\n return;\n }\n throw new ServerError(\n value.errorCodes?.join(\" \") || Constants.EMPTY_STRING,\n value.errorMessage,\n value.subError\n );\n }\n }\n\n /**\n * Performs necessary throttling checks after a network request.\n * @param cacheManager\n * @param thumbprint\n * @param response\n */\n static postProcess(\n cacheManager: CacheManager,\n thumbprint: RequestThumbprint,\n response: NetworkResponse\n ): void {\n if (\n ThrottlingUtils.checkResponseStatus(response) ||\n ThrottlingUtils.checkResponseForRetryAfter(response)\n ) {\n const thumbprintValue: ThrottlingEntity = {\n throttleTime: ThrottlingUtils.calculateThrottleTime(\n parseInt(response.headers[HeaderNames.RETRY_AFTER])\n ),\n error: response.body.error,\n errorCodes: response.body.error_codes,\n errorMessage: response.body.error_description,\n subError: response.body.suberror,\n };\n cacheManager.setThrottlingCache(\n ThrottlingUtils.generateThrottlingStorageKey(thumbprint),\n thumbprintValue\n );\n }\n }\n\n /**\n * Checks a NetworkResponse object's status codes against 429 or 5xx\n * @param response\n */\n static checkResponseStatus(\n response: NetworkResponse\n ): boolean {\n return (\n response.status === 429 ||\n (response.status >= 500 && response.status < 600)\n );\n }\n\n /**\n * Checks a NetworkResponse object's RetryAfter header\n * @param response\n */\n static checkResponseForRetryAfter(\n response: NetworkResponse\n ): boolean {\n if (response.headers) {\n return (\n response.headers.hasOwnProperty(HeaderNames.RETRY_AFTER) &&\n (response.status < 200 || response.status >= 300)\n );\n }\n return false;\n }\n\n /**\n * Calculates the Unix-time value for a throttle to expire given throttleTime in seconds.\n * @param throttleTime\n */\n static calculateThrottleTime(throttleTime: number): number {\n const time = throttleTime <= 0 ? 0 : throttleTime;\n\n const currentSeconds = Date.now() / 1000;\n return Math.floor(\n Math.min(\n currentSeconds +\n (time || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS),\n currentSeconds +\n ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS\n ) * 1000\n );\n }\n\n static removeThrottle(\n cacheManager: CacheManager,\n clientId: string,\n request: BaseAuthRequest,\n homeAccountIdentifier?: string\n ): void {\n const thumbprint: RequestThumbprint = {\n clientId: clientId,\n authority: request.authority,\n scopes: request.scopes,\n homeAccountIdentifier: homeAccountIdentifier,\n claims: request.claims,\n authenticationScheme: request.authenticationScheme,\n resourceRequestMethod: request.resourceRequestMethod,\n resourceRequestUri: request.resourceRequestUri,\n shrClaims: request.shrClaims,\n sshKid: request.sshKid,\n };\n\n const key = this.generateThrottlingStorageKey(thumbprint);\n cacheManager.removeItem(key);\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { INetworkModule, NetworkRequestOptions } from \"./INetworkModule\";\nimport { RequestThumbprint } from \"./RequestThumbprint\";\nimport { ThrottlingUtils } from \"./ThrottlingUtils\";\nimport { CacheManager } from \"../cache/CacheManager\";\nimport { AuthError } from \"../error/AuthError\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse\";\n\nexport type NetworkResponse = {\n headers: Record;\n body: T;\n status: number;\n};\n\nexport type UrlToHttpRequestOptions = {\n protocol: string;\n hostname: string;\n hash: string;\n search: string;\n pathname: string;\n path: string;\n href: string;\n port?: number;\n auth?: string;\n};\n\n/** @internal */\nexport class NetworkManager {\n private networkClient: INetworkModule;\n private cacheManager: CacheManager;\n\n constructor(networkClient: INetworkModule, cacheManager: CacheManager) {\n this.networkClient = networkClient;\n this.cacheManager = cacheManager;\n }\n\n /**\n * Wraps sendPostRequestAsync with necessary preflight and postflight logic\n * @param thumbprint\n * @param tokenEndpoint\n * @param options\n */\n async sendPostRequest(\n thumbprint: RequestThumbprint,\n tokenEndpoint: string,\n options: NetworkRequestOptions\n ): Promise> {\n ThrottlingUtils.preProcess(this.cacheManager, thumbprint);\n\n let response;\n try {\n response = await this.networkClient.sendPostRequestAsync(\n tokenEndpoint,\n options\n );\n } catch (e) {\n if (e instanceof AuthError) {\n throw e;\n } else {\n throw ClientAuthError.createNetworkError(\n tokenEndpoint,\n e as string\n );\n }\n }\n\n ThrottlingUtils.postProcess(this.cacheManager, thumbprint, response);\n\n return response;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ClientConfigurationError } from \"../error/ClientConfigurationError\";\nimport { PromptValue, CodeChallengeMethodValues } from \"../utils/Constants\";\nimport { StringDict } from \"../utils/MsalTypes\";\n\n/**\n * Validates server consumable params from the \"request\" objects\n */\nexport class RequestValidator {\n /**\n * Utility to check if the `redirectUri` in the request is a non-null value\n * @param redirectUri\n */\n static validateRedirectUri(redirectUri: string): void {\n if (!redirectUri) {\n throw ClientConfigurationError.createRedirectUriEmptyError();\n }\n }\n\n /**\n * Utility to validate prompt sent by the user in the request\n * @param prompt\n */\n static validatePrompt(prompt: string): void {\n const promptValues = [];\n\n for (const value in PromptValue) {\n promptValues.push(PromptValue[value]);\n }\n\n if (promptValues.indexOf(prompt) < 0) {\n throw ClientConfigurationError.createInvalidPromptError(prompt);\n }\n }\n\n static validateClaims(claims: string): void {\n try {\n JSON.parse(claims);\n } catch (e) {\n throw ClientConfigurationError.createInvalidClaimsRequestError();\n }\n }\n\n /**\n * Utility to validate code_challenge and code_challenge_method\n * @param codeChallenge\n * @param codeChallengeMethod\n */\n static validateCodeChallengeParams(\n codeChallenge: string,\n codeChallengeMethod: string\n ): void {\n if (!codeChallenge || !codeChallengeMethod) {\n throw ClientConfigurationError.createInvalidCodeChallengeParamsError();\n } else {\n this.validateCodeChallengeMethod(codeChallengeMethod);\n }\n }\n\n /**\n * Utility to validate code_challenge_method\n * @param codeChallengeMethod\n */\n static validateCodeChallengeMethod(codeChallengeMethod: string): void {\n if (\n [\n CodeChallengeMethodValues.PLAIN,\n CodeChallengeMethodValues.S256,\n ].indexOf(codeChallengeMethod) < 0\n ) {\n throw ClientConfigurationError.createInvalidCodeChallengeMethodError();\n }\n }\n\n /**\n * Removes unnecessary, duplicate, and empty string query parameters from extraQueryParameters\n * @param request\n */\n static sanitizeEQParams(\n eQParams: StringDict,\n queryParams: Map\n ): StringDict {\n if (!eQParams) {\n return {};\n }\n\n // Remove any query parameters already included in SSO params\n queryParams.forEach((_value, key) => {\n if (eQParams[key]) {\n delete eQParams[key];\n }\n });\n\n // remove empty string parameters\n return Object.fromEntries(\n Object.entries(eQParams).filter((kv) => kv[1] !== \"\")\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AADServerParamKeys,\n Constants,\n ResponseMode,\n SSOTypes,\n CLIENT_INFO,\n AuthenticationScheme,\n ClaimsRequestKeys,\n PasswordGrantConstants,\n OIDC_DEFAULT_SCOPES,\n ThrottlingConstants,\n HeaderNames,\n} from \"../utils/Constants\";\nimport { ScopeSet } from \"./ScopeSet\";\nimport { ClientConfigurationError } from \"../error/ClientConfigurationError\";\nimport { StringDict } from \"../utils/MsalTypes\";\nimport { RequestValidator } from \"./RequestValidator\";\nimport {\n ApplicationTelemetry,\n LibraryInfo,\n} from \"../config/ClientConfiguration\";\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager\";\nimport { ClientInfo } from \"../account/ClientInfo\";\n\n/** @internal */\nexport class RequestParameterBuilder {\n private parameters: Map;\n\n constructor() {\n this.parameters = new Map();\n }\n\n /**\n * add response_type = code\n */\n addResponseTypeCode(): void {\n this.parameters.set(\n AADServerParamKeys.RESPONSE_TYPE,\n encodeURIComponent(Constants.CODE_RESPONSE_TYPE)\n );\n }\n\n /**\n * add response_type = token id_token\n */\n addResponseTypeForTokenAndIdToken(): void {\n this.parameters.set(\n AADServerParamKeys.RESPONSE_TYPE,\n encodeURIComponent(\n `${Constants.TOKEN_RESPONSE_TYPE} ${Constants.ID_TOKEN_RESPONSE_TYPE}`\n )\n );\n }\n\n /**\n * add response_mode. defaults to query.\n * @param responseMode\n */\n addResponseMode(responseMode?: ResponseMode): void {\n this.parameters.set(\n AADServerParamKeys.RESPONSE_MODE,\n encodeURIComponent(responseMode ? responseMode : ResponseMode.QUERY)\n );\n }\n\n /**\n * Add flag to indicate STS should attempt to use WAM if available\n */\n addNativeBroker(): void {\n this.parameters.set(\n AADServerParamKeys.NATIVE_BROKER,\n encodeURIComponent(\"1\")\n );\n }\n\n /**\n * add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios\n * @param scopeSet\n * @param addOidcScopes\n */\n addScopes(\n scopes: string[],\n addOidcScopes: boolean = true,\n defaultScopes: Array = OIDC_DEFAULT_SCOPES\n ): void {\n // Always add openid to the scopes when adding OIDC scopes\n if (\n addOidcScopes &&\n !defaultScopes.includes(\"openid\") &&\n !scopes.includes(\"openid\")\n ) {\n defaultScopes.push(\"openid\");\n }\n const requestScopes = addOidcScopes\n ? [...(scopes || []), ...defaultScopes]\n : scopes || [];\n const scopeSet = new ScopeSet(requestScopes);\n this.parameters.set(\n AADServerParamKeys.SCOPE,\n encodeURIComponent(scopeSet.printScopes())\n );\n }\n\n /**\n * add clientId\n * @param clientId\n */\n addClientId(clientId: string): void {\n this.parameters.set(\n AADServerParamKeys.CLIENT_ID,\n encodeURIComponent(clientId)\n );\n }\n\n /**\n * add redirect_uri\n * @param redirectUri\n */\n addRedirectUri(redirectUri: string): void {\n RequestValidator.validateRedirectUri(redirectUri);\n this.parameters.set(\n AADServerParamKeys.REDIRECT_URI,\n encodeURIComponent(redirectUri)\n );\n }\n\n /**\n * add post logout redirectUri\n * @param redirectUri\n */\n addPostLogoutRedirectUri(redirectUri: string): void {\n RequestValidator.validateRedirectUri(redirectUri);\n this.parameters.set(\n AADServerParamKeys.POST_LOGOUT_URI,\n encodeURIComponent(redirectUri)\n );\n }\n\n /**\n * add id_token_hint to logout request\n * @param idTokenHint\n */\n addIdTokenHint(idTokenHint: string): void {\n this.parameters.set(\n AADServerParamKeys.ID_TOKEN_HINT,\n encodeURIComponent(idTokenHint)\n );\n }\n\n /**\n * add domain_hint\n * @param domainHint\n */\n addDomainHint(domainHint: string): void {\n this.parameters.set(\n SSOTypes.DOMAIN_HINT,\n encodeURIComponent(domainHint)\n );\n }\n\n /**\n * add login_hint\n * @param loginHint\n */\n addLoginHint(loginHint: string): void {\n this.parameters.set(SSOTypes.LOGIN_HINT, encodeURIComponent(loginHint));\n }\n\n /**\n * Adds the CCS (Cache Credential Service) query parameter for login_hint\n * @param loginHint\n */\n addCcsUpn(loginHint: string): void {\n this.parameters.set(\n HeaderNames.CCS_HEADER,\n encodeURIComponent(`UPN:${loginHint}`)\n );\n }\n\n /**\n * Adds the CCS (Cache Credential Service) query parameter for account object\n * @param loginHint\n */\n addCcsOid(clientInfo: ClientInfo): void {\n this.parameters.set(\n HeaderNames.CCS_HEADER,\n encodeURIComponent(`Oid:${clientInfo.uid}@${clientInfo.utid}`)\n );\n }\n\n /**\n * add sid\n * @param sid\n */\n addSid(sid: string): void {\n this.parameters.set(SSOTypes.SID, encodeURIComponent(sid));\n }\n\n /**\n * add claims\n * @param claims\n */\n addClaims(claims?: string, clientCapabilities?: Array): void {\n const mergedClaims = this.addClientCapabilitiesToClaims(\n claims,\n clientCapabilities\n );\n RequestValidator.validateClaims(mergedClaims);\n this.parameters.set(\n AADServerParamKeys.CLAIMS,\n encodeURIComponent(mergedClaims)\n );\n }\n\n /**\n * add correlationId\n * @param correlationId\n */\n addCorrelationId(correlationId: string): void {\n this.parameters.set(\n AADServerParamKeys.CLIENT_REQUEST_ID,\n encodeURIComponent(correlationId)\n );\n }\n\n /**\n * add library info query params\n * @param libraryInfo\n */\n addLibraryInfo(libraryInfo: LibraryInfo): void {\n // Telemetry Info\n this.parameters.set(AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku);\n this.parameters.set(\n AADServerParamKeys.X_CLIENT_VER,\n libraryInfo.version\n );\n if (libraryInfo.os) {\n this.parameters.set(AADServerParamKeys.X_CLIENT_OS, libraryInfo.os);\n }\n if (libraryInfo.cpu) {\n this.parameters.set(\n AADServerParamKeys.X_CLIENT_CPU,\n libraryInfo.cpu\n );\n }\n }\n\n /**\n * Add client telemetry parameters\n * @param appTelemetry\n */\n addApplicationTelemetry(appTelemetry: ApplicationTelemetry): void {\n if (appTelemetry?.appName) {\n this.parameters.set(\n AADServerParamKeys.X_APP_NAME,\n appTelemetry.appName\n );\n }\n\n if (appTelemetry?.appVersion) {\n this.parameters.set(\n AADServerParamKeys.X_APP_VER,\n appTelemetry.appVersion\n );\n }\n }\n\n /**\n * add prompt\n * @param prompt\n */\n addPrompt(prompt: string): void {\n RequestValidator.validatePrompt(prompt);\n this.parameters.set(\n `${AADServerParamKeys.PROMPT}`,\n encodeURIComponent(prompt)\n );\n }\n\n /**\n * add state\n * @param state\n */\n addState(state: string): void {\n if (state) {\n this.parameters.set(\n AADServerParamKeys.STATE,\n encodeURIComponent(state)\n );\n }\n }\n\n /**\n * add nonce\n * @param nonce\n */\n addNonce(nonce: string): void {\n this.parameters.set(\n AADServerParamKeys.NONCE,\n encodeURIComponent(nonce)\n );\n }\n\n /**\n * add code_challenge and code_challenge_method\n * - throw if either of them are not passed\n * @param codeChallenge\n * @param codeChallengeMethod\n */\n addCodeChallengeParams(\n codeChallenge: string,\n codeChallengeMethod: string\n ): void {\n RequestValidator.validateCodeChallengeParams(\n codeChallenge,\n codeChallengeMethod\n );\n if (codeChallenge && codeChallengeMethod) {\n this.parameters.set(\n AADServerParamKeys.CODE_CHALLENGE,\n encodeURIComponent(codeChallenge)\n );\n this.parameters.set(\n AADServerParamKeys.CODE_CHALLENGE_METHOD,\n encodeURIComponent(codeChallengeMethod)\n );\n } else {\n throw ClientConfigurationError.createInvalidCodeChallengeParamsError();\n }\n }\n\n /**\n * add the `authorization_code` passed by the user to exchange for a token\n * @param code\n */\n addAuthorizationCode(code: string): void {\n this.parameters.set(AADServerParamKeys.CODE, encodeURIComponent(code));\n }\n\n /**\n * add the `authorization_code` passed by the user to exchange for a token\n * @param code\n */\n addDeviceCode(code: string): void {\n this.parameters.set(\n AADServerParamKeys.DEVICE_CODE,\n encodeURIComponent(code)\n );\n }\n\n /**\n * add the `refreshToken` passed by the user\n * @param refreshToken\n */\n addRefreshToken(refreshToken: string): void {\n this.parameters.set(\n AADServerParamKeys.REFRESH_TOKEN,\n encodeURIComponent(refreshToken)\n );\n }\n\n /**\n * add the `code_verifier` passed by the user to exchange for a token\n * @param codeVerifier\n */\n addCodeVerifier(codeVerifier: string): void {\n this.parameters.set(\n AADServerParamKeys.CODE_VERIFIER,\n encodeURIComponent(codeVerifier)\n );\n }\n\n /**\n * add client_secret\n * @param clientSecret\n */\n addClientSecret(clientSecret: string): void {\n this.parameters.set(\n AADServerParamKeys.CLIENT_SECRET,\n encodeURIComponent(clientSecret)\n );\n }\n\n /**\n * add clientAssertion for confidential client flows\n * @param clientAssertion\n */\n addClientAssertion(clientAssertion: string): void {\n if (clientAssertion) {\n this.parameters.set(\n AADServerParamKeys.CLIENT_ASSERTION,\n encodeURIComponent(clientAssertion)\n );\n }\n }\n\n /**\n * add clientAssertionType for confidential client flows\n * @param clientAssertionType\n */\n addClientAssertionType(clientAssertionType: string): void {\n if (clientAssertionType) {\n this.parameters.set(\n AADServerParamKeys.CLIENT_ASSERTION_TYPE,\n encodeURIComponent(clientAssertionType)\n );\n }\n }\n\n /**\n * add OBO assertion for confidential client flows\n * @param clientAssertion\n */\n addOboAssertion(oboAssertion: string): void {\n this.parameters.set(\n AADServerParamKeys.OBO_ASSERTION,\n encodeURIComponent(oboAssertion)\n );\n }\n\n /**\n * add grant type\n * @param grantType\n */\n addRequestTokenUse(tokenUse: string): void {\n this.parameters.set(\n AADServerParamKeys.REQUESTED_TOKEN_USE,\n encodeURIComponent(tokenUse)\n );\n }\n\n /**\n * add grant type\n * @param grantType\n */\n addGrantType(grantType: string): void {\n this.parameters.set(\n AADServerParamKeys.GRANT_TYPE,\n encodeURIComponent(grantType)\n );\n }\n\n /**\n * add client info\n *\n */\n addClientInfo(): void {\n this.parameters.set(CLIENT_INFO, \"1\");\n }\n\n /**\n * add extraQueryParams\n * @param eQParams\n */\n addExtraQueryParameters(eQParams: StringDict): void {\n const sanitizedEQParams = RequestValidator.sanitizeEQParams(\n eQParams,\n this.parameters\n );\n Object.keys(sanitizedEQParams).forEach((key) => {\n this.parameters.set(key, eQParams[key]);\n });\n }\n\n addClientCapabilitiesToClaims(\n claims?: string,\n clientCapabilities?: Array\n ): string {\n let mergedClaims: object;\n\n // Parse provided claims into JSON object or initialize empty object\n if (!claims) {\n mergedClaims = {};\n } else {\n try {\n mergedClaims = JSON.parse(claims);\n } catch (e) {\n throw ClientConfigurationError.createInvalidClaimsRequestError();\n }\n }\n\n if (clientCapabilities && clientCapabilities.length > 0) {\n if (!mergedClaims.hasOwnProperty(ClaimsRequestKeys.ACCESS_TOKEN)) {\n // Add access_token key to claims object\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN] = {};\n }\n\n // Add xms_cc claim with provided clientCapabilities to access_token key\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN][\n ClaimsRequestKeys.XMS_CC\n ] = {\n values: clientCapabilities,\n };\n }\n\n return JSON.stringify(mergedClaims);\n }\n\n /**\n * adds `username` for Password Grant flow\n * @param username\n */\n addUsername(username: string): void {\n this.parameters.set(\n PasswordGrantConstants.username,\n encodeURIComponent(username)\n );\n }\n\n /**\n * adds `password` for Password Grant flow\n * @param password\n */\n addPassword(password: string): void {\n this.parameters.set(\n PasswordGrantConstants.password,\n encodeURIComponent(password)\n );\n }\n\n /**\n * add pop_jwk to query params\n * @param cnfString\n */\n addPopToken(cnfString: string): void {\n if (cnfString) {\n this.parameters.set(\n AADServerParamKeys.TOKEN_TYPE,\n AuthenticationScheme.POP\n );\n this.parameters.set(\n AADServerParamKeys.REQ_CNF,\n encodeURIComponent(cnfString)\n );\n }\n }\n\n /**\n * add SSH JWK and key ID to query params\n */\n addSshJwk(sshJwkString: string): void {\n if (sshJwkString) {\n this.parameters.set(\n AADServerParamKeys.TOKEN_TYPE,\n AuthenticationScheme.SSH\n );\n this.parameters.set(\n AADServerParamKeys.REQ_CNF,\n encodeURIComponent(sshJwkString)\n );\n }\n }\n\n /**\n * add server telemetry fields\n * @param serverTelemetryManager\n */\n addServerTelemetry(serverTelemetryManager: ServerTelemetryManager): void {\n this.parameters.set(\n AADServerParamKeys.X_CLIENT_CURR_TELEM,\n serverTelemetryManager.generateCurrentRequestHeaderValue()\n );\n this.parameters.set(\n AADServerParamKeys.X_CLIENT_LAST_TELEM,\n serverTelemetryManager.generateLastRequestHeaderValue()\n );\n }\n\n /**\n * Adds parameter that indicates to the server that throttling is supported\n */\n addThrottling(): void {\n this.parameters.set(\n AADServerParamKeys.X_MS_LIB_CAPABILITY,\n ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE\n );\n }\n\n /**\n * Adds logout_hint parameter for \"silent\" logout which prevent server account picker\n */\n addLogoutHint(logoutHint: string): void {\n this.parameters.set(\n AADServerParamKeys.LOGOUT_HINT,\n encodeURIComponent(logoutHint)\n );\n }\n\n /**\n * Utility to create a URL from the params map\n */\n createQueryString(): string {\n const queryParameterArray: Array = new Array();\n\n this.parameters.forEach((value, key) => {\n queryParameterArray.push(`${key}=${value}`);\n });\n\n return queryParameterArray.join(\"&\");\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientConfiguration,\n buildClientConfiguration,\n CommonClientConfiguration,\n} from \"../config/ClientConfiguration\";\nimport { INetworkModule } from \"../network/INetworkModule\";\nimport { NetworkManager, NetworkResponse } from \"../network/NetworkManager\";\nimport { ICrypto } from \"../crypto/ICrypto\";\nimport { Authority } from \"../authority/Authority\";\nimport { Logger } from \"../logger/Logger\";\nimport { Constants, HeaderNames } from \"../utils/Constants\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse\";\nimport { CacheManager } from \"../cache/CacheManager\";\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager\";\nimport { RequestThumbprint } from \"../network/RequestThumbprint\";\nimport { version, name } from \"../packageMetadata\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\nimport { CcsCredential, CcsCredentialType } from \"../account/CcsCredential\";\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient\";\nimport { RequestParameterBuilder } from \"../request/RequestParameterBuilder\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent\";\n\n/**\n * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.\n * @internal\n */\nexport abstract class BaseClient {\n // Logger object\n public logger: Logger;\n\n // Application config\n protected config: CommonClientConfiguration;\n\n // Crypto Interface\n protected cryptoUtils: ICrypto;\n\n // Storage Interface\n protected cacheManager: CacheManager;\n\n // Network Interface\n protected networkClient: INetworkModule;\n\n // Server Telemetry Manager\n protected serverTelemetryManager: ServerTelemetryManager | null;\n\n // Network Manager\n protected networkManager: NetworkManager;\n\n // Default authority object\n public authority: Authority;\n\n // Performance telemetry client\n protected performanceClient?: IPerformanceClient;\n\n protected constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n // Set the configuration\n this.config = buildClientConfiguration(configuration);\n\n // Initialize the logger\n this.logger = new Logger(this.config.loggerOptions, name, version);\n\n // Initialize crypto\n this.cryptoUtils = this.config.cryptoInterface;\n\n // Initialize storage interface\n this.cacheManager = this.config.storageInterface;\n\n // Set the network interface\n this.networkClient = this.config.networkInterface;\n\n // Set the NetworkManager\n this.networkManager = new NetworkManager(\n this.networkClient,\n this.cacheManager\n );\n\n // Set TelemetryManager\n this.serverTelemetryManager = this.config.serverTelemetryManager;\n\n // set Authority\n this.authority = this.config.authOptions.authority;\n\n // set performance telemetry client\n this.performanceClient = performanceClient;\n }\n\n /**\n * Creates default headers for requests to token endpoint\n */\n protected createTokenRequestHeaders(\n ccsCred?: CcsCredential\n ): Record {\n const headers: Record = {};\n headers[HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE;\n if (!this.config.systemOptions.preventCorsPreflight && ccsCred) {\n switch (ccsCred.type) {\n case CcsCredentialType.HOME_ACCOUNT_ID:\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n ccsCred.credential\n );\n headers[\n HeaderNames.CCS_HEADER\n ] = `Oid:${clientInfo.uid}@${clientInfo.utid}`;\n } catch (e) {\n this.logger.verbose(\n \"Could not parse home account ID for CCS Header: \" +\n e\n );\n }\n break;\n case CcsCredentialType.UPN:\n headers[\n HeaderNames.CCS_HEADER\n ] = `UPN: ${ccsCred.credential}`;\n break;\n }\n }\n return headers;\n }\n\n /**\n * Http post to token endpoint\n * @param tokenEndpoint\n * @param queryString\n * @param headers\n * @param thumbprint\n */\n protected async executePostToTokenEndpoint(\n tokenEndpoint: string,\n queryString: string,\n headers: Record,\n thumbprint: RequestThumbprint,\n correlationId: string\n ): Promise> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.BaseClientCreateTokenRequestHeaders,\n correlationId\n );\n const response =\n await this.networkManager.sendPostRequest(\n thumbprint,\n tokenEndpoint,\n { body: queryString, headers: headers }\n );\n this.performanceClient?.addFields(\n {\n refreshTokenSize: response.body.refresh_token?.length || 0,\n httpVerToken:\n response.headers?.[HeaderNames.X_MS_HTTP_VERSION] || \"\",\n },\n correlationId\n );\n\n if (\n this.config.serverTelemetryManager &&\n response.status < 500 &&\n response.status !== 429\n ) {\n // Telemetry data successfully logged by server, clear Telemetry cache\n this.config.serverTelemetryManager.clearTelemetryCache();\n }\n\n return response;\n }\n\n /**\n * Updates the authority object of the client. Endpoint discovery must be completed.\n * @param updatedAuthority\n */\n updateAuthority(updatedAuthority: Authority): void {\n if (!updatedAuthority.discoveryComplete()) {\n throw ClientAuthError.createEndpointDiscoveryIncompleteError(\n \"Updated authority has not completed endpoint discovery.\"\n );\n }\n this.authority = updatedAuthority;\n }\n\n /**\n * Creates query string for the /token request\n * @param request\n */\n createTokenQueryParameters(request: BaseAuthRequest): string {\n const parameterBuilder = new RequestParameterBuilder();\n\n if (request.tokenQueryParameters) {\n parameterBuilder.addExtraQueryParameters(\n request.tokenQueryParameters\n );\n }\n\n return parameterBuilder.createQueryString();\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ICrypto, SignedHttpRequestParameters } from \"./ICrypto\";\nimport { TimeUtils } from \"../utils/TimeUtils\";\nimport { UrlString } from \"../url/UrlString\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent\";\n\n/**\n * See eSTS docs for more info.\n * - A kid element, with the value containing an RFC 7638-compliant JWK thumbprint that is base64 encoded.\n * - xms_ksl element, representing the storage location of the key's secret component on the client device. One of two values:\n * - sw: software storage\n * - uhw: hardware storage\n */\ntype ReqCnf = {\n kid: string;\n xms_ksl: KeyLocation;\n};\n\nexport type ReqCnfData = {\n kid: string;\n reqCnfString: string;\n reqCnfHash: string;\n};\n\nconst KeyLocation = {\n SW: \"sw\",\n UHW: \"uhw\",\n} as const;\nexport type KeyLocation = (typeof KeyLocation)[keyof typeof KeyLocation];\n\n/** @internal */\nexport class PopTokenGenerator {\n private cryptoUtils: ICrypto;\n private performanceClient?: IPerformanceClient;\n\n constructor(cryptoUtils: ICrypto, performanceClient?: IPerformanceClient) {\n this.cryptoUtils = cryptoUtils;\n this.performanceClient = performanceClient;\n }\n\n /**\n * Generates the req_cnf validated at the RP in the POP protocol for SHR parameters\n * and returns an object containing the keyid, the full req_cnf string and the req_cnf string hash\n * @param request\n * @returns\n */\n async generateCnf(\n request: SignedHttpRequestParameters\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.PopTokenGenerateCnf,\n request.correlationId\n );\n\n this.performanceClient?.setPreQueueTime(\n PerformanceEvents.PopTokenGenerateKid,\n request.correlationId\n );\n const reqCnf = await this.generateKid(request);\n const reqCnfString: string = this.cryptoUtils.base64Encode(\n JSON.stringify(reqCnf)\n );\n\n return {\n kid: reqCnf.kid,\n reqCnfString,\n reqCnfHash: await this.cryptoUtils.hashString(reqCnfString),\n };\n }\n\n /**\n * Generates key_id for a SHR token request\n * @param request\n * @returns\n */\n async generateKid(request: SignedHttpRequestParameters): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.PopTokenGenerateKid,\n request.correlationId\n );\n\n const kidThumbprint = await this.cryptoUtils.getPublicKeyThumbprint(\n request\n );\n\n return {\n kid: kidThumbprint,\n xms_ksl: KeyLocation.SW,\n };\n }\n\n /**\n * Signs the POP access_token with the local generated key-pair\n * @param accessToken\n * @param request\n * @returns\n */\n async signPopToken(\n accessToken: string,\n keyId: string,\n request: SignedHttpRequestParameters\n ): Promise {\n return this.signPayload(accessToken, keyId, request);\n }\n\n /**\n * Utility function to generate the signed JWT for an access_token\n * @param payload\n * @param kid\n * @param request\n * @param claims\n * @returns\n */\n async signPayload(\n payload: string,\n keyId: string,\n request: SignedHttpRequestParameters,\n claims?: object\n ): Promise {\n // Deconstruct request to extract SHR parameters\n const {\n resourceRequestMethod,\n resourceRequestUri,\n shrClaims,\n shrNonce,\n } = request;\n\n const resourceUrlString = resourceRequestUri\n ? new UrlString(resourceRequestUri)\n : undefined;\n const resourceUrlComponents = resourceUrlString?.getUrlComponents();\n return await this.cryptoUtils.signJwt(\n {\n at: payload,\n ts: TimeUtils.nowSeconds(),\n m: resourceRequestMethod?.toUpperCase(),\n u: resourceUrlComponents?.HostNameAndPort,\n nonce: shrNonce || this.cryptoUtils.createNewGuid(),\n p: resourceUrlComponents?.AbsolutePath,\n q: resourceUrlComponents?.QueryString\n ? [[], resourceUrlComponents.QueryString]\n : undefined,\n client_claims: shrClaims || undefined,\n ...claims,\n },\n keyId,\n request.correlationId\n );\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISerializableTokenCache } from \"../interface/ISerializableTokenCache\";\n\n/**\n * This class instance helps track the memory changes facilitating\n * decisions to read from and write to the persistent cache\n */ export class TokenCacheContext {\n /**\n * boolean indicating cache change\n */\n hasChanged: boolean;\n /**\n * serializable token cache interface\n */\n cache: ISerializableTokenCache;\n\n constructor(tokenCache: ISerializableTokenCache, hasChanged: boolean) {\n this.cache = tokenCache;\n this.hasChanged = hasChanged;\n }\n\n /**\n * boolean which indicates the changes in cache\n */\n get cacheHasChanged(): boolean {\n return this.hasChanged;\n }\n\n /**\n * function to retrieve the token cache\n */\n get tokenCache(): ISerializableTokenCache {\n return this.cache;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ServerAuthorizationTokenResponse } from \"./ServerAuthorizationTokenResponse\";\nimport { buildClientInfo } from \"../account/ClientInfo\";\nimport { ICrypto } from \"../crypto/ICrypto\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\nimport { ServerAuthorizationCodeResponse } from \"./ServerAuthorizationCodeResponse\";\nimport { Logger } from \"../logger/Logger\";\nimport { ServerError } from \"../error/ServerError\";\nimport { ScopeSet } from \"../request/ScopeSet\";\nimport { AuthenticationResult } from \"./AuthenticationResult\";\nimport { AccountEntity } from \"../cache/entities/AccountEntity\";\nimport { Authority } from \"../authority/Authority\";\nimport { IdTokenEntity } from \"../cache/entities/IdTokenEntity\";\nimport { AccessTokenEntity } from \"../cache/entities/AccessTokenEntity\";\nimport { RefreshTokenEntity } from \"../cache/entities/RefreshTokenEntity\";\nimport { InteractionRequiredAuthError } from \"../error/InteractionRequiredAuthError\";\nimport { CacheRecord } from \"../cache/entities/CacheRecord\";\nimport { CacheManager } from \"../cache/CacheManager\";\nimport { ProtocolUtils, RequestStateObject } from \"../utils/ProtocolUtils\";\nimport {\n AuthenticationScheme,\n Constants,\n THE_FAMILY_ID,\n HttpStatus,\n} from \"../utils/Constants\";\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator\";\nimport { AppMetadataEntity } from \"../cache/entities/AppMetadataEntity\";\nimport { ICachePlugin } from \"../cache/interface/ICachePlugin\";\nimport { TokenCacheContext } from \"../cache/persistence/TokenCacheContext\";\nimport { ISerializableTokenCache } from \"../cache/interface/ISerializableTokenCache\";\nimport { AuthorizationCodePayload } from \"./AuthorizationCodePayload\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent\";\nimport { checkMaxAge, extractTokenClaims } from \"../account/AuthToken\";\nimport { TokenClaims } from \"../account/TokenClaims\";\n\n/**\n * Class that handles response parsing.\n * @internal\n */\nexport class ResponseHandler {\n private clientId: string;\n private cacheStorage: CacheManager;\n private cryptoObj: ICrypto;\n private logger: Logger;\n private homeAccountIdentifier: string;\n private serializableCache: ISerializableTokenCache | null;\n private persistencePlugin: ICachePlugin | null;\n private performanceClient?: IPerformanceClient;\n\n constructor(\n clientId: string,\n cacheStorage: CacheManager,\n cryptoObj: ICrypto,\n logger: Logger,\n serializableCache: ISerializableTokenCache | null,\n persistencePlugin: ICachePlugin | null,\n performanceClient?: IPerformanceClient\n ) {\n this.clientId = clientId;\n this.cacheStorage = cacheStorage;\n this.cryptoObj = cryptoObj;\n this.logger = logger;\n this.serializableCache = serializableCache;\n this.persistencePlugin = persistencePlugin;\n this.performanceClient = performanceClient;\n }\n\n /**\n * Function which validates server authorization code response.\n * @param serverResponseHash\n * @param cachedState\n * @param cryptoObj\n */\n validateServerAuthorizationCodeResponse(\n serverResponseHash: ServerAuthorizationCodeResponse,\n cachedState: string,\n cryptoObj: ICrypto\n ): void {\n if (!serverResponseHash.state || !cachedState) {\n throw serverResponseHash.state\n ? ClientAuthError.createStateNotFoundError(\"Cached State\")\n : ClientAuthError.createStateNotFoundError(\"Server State\");\n }\n\n let decodedServerResponseHash: string;\n let decodedCachedState: string;\n\n try {\n decodedServerResponseHash = decodeURIComponent(\n serverResponseHash.state\n );\n } catch (e) {\n throw ClientAuthError.createInvalidStateError(\n serverResponseHash.state,\n `Server response hash URI could not be decoded`\n );\n }\n\n try {\n decodedCachedState = decodeURIComponent(cachedState);\n } catch (e) {\n throw ClientAuthError.createInvalidStateError(\n serverResponseHash.state,\n `Cached state URI could not be decoded`\n );\n }\n\n if (decodedServerResponseHash !== decodedCachedState) {\n throw ClientAuthError.createStateMismatchError();\n }\n\n // Check for error\n if (\n serverResponseHash.error ||\n serverResponseHash.error_description ||\n serverResponseHash.suberror\n ) {\n if (\n InteractionRequiredAuthError.isInteractionRequiredError(\n serverResponseHash.error,\n serverResponseHash.error_description,\n serverResponseHash.suberror\n )\n ) {\n throw new InteractionRequiredAuthError(\n serverResponseHash.error || Constants.EMPTY_STRING,\n serverResponseHash.error_description,\n serverResponseHash.suberror,\n serverResponseHash.timestamp || Constants.EMPTY_STRING,\n serverResponseHash.trace_id || Constants.EMPTY_STRING,\n serverResponseHash.correlation_id || Constants.EMPTY_STRING,\n serverResponseHash.claims || Constants.EMPTY_STRING\n );\n }\n\n throw new ServerError(\n serverResponseHash.error || Constants.EMPTY_STRING,\n serverResponseHash.error_description,\n serverResponseHash.suberror\n );\n }\n\n if (serverResponseHash.client_info) {\n buildClientInfo(serverResponseHash.client_info, cryptoObj);\n }\n }\n\n /**\n * Function which validates server authorization token response.\n * @param serverResponse\n * @param refreshAccessToken\n */\n validateTokenResponse(\n serverResponse: ServerAuthorizationTokenResponse,\n refreshAccessToken?: boolean\n ): void {\n // Check for error\n if (\n serverResponse.error ||\n serverResponse.error_description ||\n serverResponse.suberror\n ) {\n const errString = `${serverResponse.error_codes} - [${serverResponse.timestamp}]: ${serverResponse.error_description} - Correlation ID: ${serverResponse.correlation_id} - Trace ID: ${serverResponse.trace_id}`;\n const serverError = new ServerError(\n serverResponse.error,\n errString,\n serverResponse.suberror\n );\n\n // check if 500 error\n if (\n refreshAccessToken &&\n serverResponse.status &&\n serverResponse.status >= HttpStatus.SERVER_ERROR_RANGE_START &&\n serverResponse.status <= HttpStatus.SERVER_ERROR_RANGE_END\n ) {\n this.logger.warning(\n `executeTokenRequest:validateTokenResponse - AAD is currently unavailable and the access token is unable to be refreshed.\\n${serverError}`\n );\n\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\n return;\n // check if 400 error\n } else if (\n refreshAccessToken &&\n serverResponse.status &&\n serverResponse.status >= HttpStatus.CLIENT_ERROR_RANGE_START &&\n serverResponse.status <= HttpStatus.CLIENT_ERROR_RANGE_END\n ) {\n this.logger.warning(\n `executeTokenRequest:validateTokenResponse - AAD is currently available but is unable to refresh the access token.\\n${serverError}`\n );\n\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\n return;\n }\n\n if (\n InteractionRequiredAuthError.isInteractionRequiredError(\n serverResponse.error,\n serverResponse.error_description,\n serverResponse.suberror\n )\n ) {\n throw new InteractionRequiredAuthError(\n serverResponse.error,\n serverResponse.error_description,\n serverResponse.suberror,\n serverResponse.timestamp || Constants.EMPTY_STRING,\n serverResponse.trace_id || Constants.EMPTY_STRING,\n serverResponse.correlation_id || Constants.EMPTY_STRING,\n serverResponse.claims || Constants.EMPTY_STRING\n );\n }\n\n throw serverError;\n }\n }\n\n /**\n * Returns a constructed token response based on given string. Also manages the cache updates and cleanups.\n * @param serverTokenResponse\n * @param authority\n */\n async handleServerTokenResponse(\n serverTokenResponse: ServerAuthorizationTokenResponse,\n authority: Authority,\n reqTimestamp: number,\n request: BaseAuthRequest,\n authCodePayload?: AuthorizationCodePayload,\n userAssertionHash?: string,\n handlingRefreshTokenResponse?: boolean,\n forceCacheRefreshTokenResponse?: boolean,\n serverRequestId?: string\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.HandleServerTokenResponse,\n serverTokenResponse.correlation_id\n );\n\n // create an idToken object (not entity)\n let idTokenClaims: TokenClaims | undefined;\n if (serverTokenResponse.id_token) {\n idTokenClaims = extractTokenClaims(\n serverTokenResponse.id_token || Constants.EMPTY_STRING,\n this.cryptoObj.base64Decode\n );\n\n // token nonce check (TODO: Add a warning if no nonce is given?)\n if (authCodePayload && authCodePayload.nonce) {\n if (idTokenClaims.nonce !== authCodePayload.nonce) {\n throw ClientAuthError.createNonceMismatchError();\n }\n }\n\n // token max_age check\n if (request.maxAge || request.maxAge === 0) {\n const authTime = idTokenClaims.auth_time;\n if (!authTime) {\n throw ClientAuthError.createAuthTimeNotFoundError();\n }\n\n checkMaxAge(authTime, request.maxAge);\n }\n }\n\n // generate homeAccountId\n this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(\n serverTokenResponse.client_info || Constants.EMPTY_STRING,\n authority.authorityType,\n this.logger,\n this.cryptoObj,\n idTokenClaims\n );\n\n // save the response tokens\n let requestStateObj: RequestStateObject | undefined;\n if (!!authCodePayload && !!authCodePayload.state) {\n requestStateObj = ProtocolUtils.parseRequestState(\n this.cryptoObj,\n authCodePayload.state\n );\n }\n\n // Add keyId from request to serverTokenResponse if defined\n serverTokenResponse.key_id =\n serverTokenResponse.key_id || request.sshKid || undefined;\n\n const cacheRecord = this.generateCacheRecord(\n serverTokenResponse,\n authority,\n reqTimestamp,\n request,\n idTokenClaims,\n userAssertionHash,\n authCodePayload\n );\n let cacheContext;\n try {\n if (this.persistencePlugin && this.serializableCache) {\n this.logger.verbose(\n \"Persistence enabled, calling beforeCacheAccess\"\n );\n cacheContext = new TokenCacheContext(\n this.serializableCache,\n true\n );\n await this.persistencePlugin.beforeCacheAccess(cacheContext);\n }\n /*\n * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.\n * If not present, we should return null, as it's the case that another application called removeAccount in between\n * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by\n * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration.\n */\n if (\n handlingRefreshTokenResponse &&\n !forceCacheRefreshTokenResponse &&\n cacheRecord.account\n ) {\n const key = cacheRecord.account.generateAccountKey();\n const account = this.cacheStorage.getAccount(key);\n if (!account) {\n this.logger.warning(\n \"Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache\"\n );\n return ResponseHandler.generateAuthenticationResult(\n this.cryptoObj,\n authority,\n cacheRecord,\n false,\n request,\n idTokenClaims,\n requestStateObj,\n undefined,\n serverRequestId\n );\n }\n }\n await this.cacheStorage.saveCacheRecord(\n cacheRecord,\n request.storeInCache\n );\n } finally {\n if (\n this.persistencePlugin &&\n this.serializableCache &&\n cacheContext\n ) {\n this.logger.verbose(\n \"Persistence enabled, calling afterCacheAccess\"\n );\n await this.persistencePlugin.afterCacheAccess(cacheContext);\n }\n }\n return ResponseHandler.generateAuthenticationResult(\n this.cryptoObj,\n authority,\n cacheRecord,\n false,\n request,\n idTokenClaims,\n requestStateObj,\n serverTokenResponse,\n serverRequestId\n );\n }\n\n /**\n * Generates CacheRecord\n * @param serverTokenResponse\n * @param idTokenObj\n * @param authority\n */\n private generateCacheRecord(\n serverTokenResponse: ServerAuthorizationTokenResponse,\n authority: Authority,\n reqTimestamp: number,\n request: BaseAuthRequest,\n idTokenClaims?: TokenClaims,\n userAssertionHash?: string,\n authCodePayload?: AuthorizationCodePayload\n ): CacheRecord {\n const env = authority.getPreferredCache();\n if (!env) {\n throw ClientAuthError.createInvalidCacheEnvironmentError();\n }\n\n // IdToken: non AAD scenarios can have empty realm\n let cachedIdToken: IdTokenEntity | undefined;\n let cachedAccount: AccountEntity | undefined;\n if (serverTokenResponse.id_token && !!idTokenClaims) {\n cachedIdToken = IdTokenEntity.createIdTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.id_token,\n this.clientId,\n idTokenClaims.tid || \"\"\n );\n\n cachedAccount = AccountEntity.createAccount(\n {\n homeAccountId: this.homeAccountIdentifier,\n idTokenClaims: idTokenClaims,\n clientInfo: serverTokenResponse.client_info,\n cloudGraphHostName: authCodePayload?.cloud_graph_host_name,\n msGraphHost: authCodePayload?.msgraph_host,\n },\n authority\n );\n }\n\n // AccessToken\n let cachedAccessToken: AccessTokenEntity | null = null;\n if (serverTokenResponse.access_token) {\n // If scopes not returned in server response, use request scopes\n const responseScopes = serverTokenResponse.scope\n ? ScopeSet.fromString(serverTokenResponse.scope)\n : new ScopeSet(request.scopes || []);\n\n /*\n * Use timestamp calculated before request\n * Server may return timestamps as strings, parse to numbers if so.\n */\n const expiresIn: number =\n (typeof serverTokenResponse.expires_in === \"string\"\n ? parseInt(serverTokenResponse.expires_in, 10)\n : serverTokenResponse.expires_in) || 0;\n const extExpiresIn: number =\n (typeof serverTokenResponse.ext_expires_in === \"string\"\n ? parseInt(serverTokenResponse.ext_expires_in, 10)\n : serverTokenResponse.ext_expires_in) || 0;\n const refreshIn: number | undefined =\n (typeof serverTokenResponse.refresh_in === \"string\"\n ? parseInt(serverTokenResponse.refresh_in, 10)\n : serverTokenResponse.refresh_in) || undefined;\n const tokenExpirationSeconds = reqTimestamp + expiresIn;\n const extendedTokenExpirationSeconds =\n tokenExpirationSeconds + extExpiresIn;\n const refreshOnSeconds =\n refreshIn && refreshIn > 0\n ? reqTimestamp + refreshIn\n : undefined;\n\n // non AAD scenarios can have empty realm\n cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.access_token || Constants.EMPTY_STRING,\n this.clientId,\n idTokenClaims?.tid || authority.tenant,\n responseScopes.printScopes(),\n tokenExpirationSeconds,\n extendedTokenExpirationSeconds,\n this.cryptoObj,\n refreshOnSeconds,\n serverTokenResponse.token_type,\n userAssertionHash,\n serverTokenResponse.key_id,\n request.claims,\n request.requestedClaimsHash\n );\n }\n\n // refreshToken\n let cachedRefreshToken: RefreshTokenEntity | null = null;\n if (serverTokenResponse.refresh_token) {\n cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.refresh_token || Constants.EMPTY_STRING,\n this.clientId,\n serverTokenResponse.foci,\n userAssertionHash\n );\n }\n\n // appMetadata\n let cachedAppMetadata: AppMetadataEntity | null = null;\n if (serverTokenResponse.foci) {\n cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(\n this.clientId,\n env,\n serverTokenResponse.foci\n );\n }\n\n return new CacheRecord(\n cachedAccount,\n cachedIdToken,\n cachedAccessToken,\n cachedRefreshToken,\n cachedAppMetadata\n );\n }\n\n /**\n * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.\n *\n * Optionally takes a state string that is set as-is in the response.\n *\n * @param cacheRecord\n * @param idTokenObj\n * @param fromTokenCache\n * @param stateString\n */\n static async generateAuthenticationResult(\n cryptoObj: ICrypto,\n authority: Authority,\n cacheRecord: CacheRecord,\n fromTokenCache: boolean,\n request: BaseAuthRequest,\n idTokenClaims?: TokenClaims,\n requestState?: RequestStateObject,\n serverTokenResponse?: ServerAuthorizationTokenResponse,\n requestId?: string\n ): Promise {\n let accessToken: string = Constants.EMPTY_STRING;\n let responseScopes: Array = [];\n let expiresOn: Date | null = null;\n let extExpiresOn: Date | undefined;\n let refreshOn: Date | undefined;\n let familyId: string = Constants.EMPTY_STRING;\n\n if (cacheRecord.accessToken) {\n if (\n cacheRecord.accessToken.tokenType === AuthenticationScheme.POP\n ) {\n const popTokenGenerator: PopTokenGenerator =\n new PopTokenGenerator(cryptoObj);\n const { secret, keyId } = cacheRecord.accessToken;\n\n if (!keyId) {\n throw ClientAuthError.createKeyIdMissingError();\n }\n\n accessToken = await popTokenGenerator.signPopToken(\n secret,\n keyId,\n request\n );\n } else {\n accessToken = cacheRecord.accessToken.secret;\n }\n responseScopes = ScopeSet.fromString(\n cacheRecord.accessToken.target\n ).asArray();\n expiresOn = new Date(\n Number(cacheRecord.accessToken.expiresOn) * 1000\n );\n extExpiresOn = new Date(\n Number(cacheRecord.accessToken.extendedExpiresOn) * 1000\n );\n if (cacheRecord.accessToken.refreshOn) {\n refreshOn = new Date(\n Number(cacheRecord.accessToken.refreshOn) * 1000\n );\n }\n }\n\n if (cacheRecord.appMetadata) {\n familyId =\n cacheRecord.appMetadata.familyId === THE_FAMILY_ID\n ? THE_FAMILY_ID\n : \"\";\n }\n const uid = idTokenClaims?.oid || idTokenClaims?.sub || \"\";\n const tid = idTokenClaims?.tid || \"\";\n\n // for hybrid + native bridge enablement, send back the native account Id\n if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {\n cacheRecord.account.nativeAccountId =\n serverTokenResponse?.spa_accountid;\n }\n\n return {\n authority: authority.canonicalAuthority,\n uniqueId: uid,\n tenantId: tid,\n scopes: responseScopes,\n account: cacheRecord.account\n ? cacheRecord.account.getAccountInfo()\n : null,\n idToken: cacheRecord?.idToken?.secret || \"\",\n idTokenClaims: idTokenClaims || {},\n accessToken: accessToken,\n fromCache: fromTokenCache,\n expiresOn: expiresOn,\n extExpiresOn: extExpiresOn,\n refreshOn: refreshOn,\n correlationId: request.correlationId,\n requestId: requestId || Constants.EMPTY_STRING,\n familyId: familyId,\n tokenType:\n cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,\n state: requestState\n ? requestState.userRequestState\n : Constants.EMPTY_STRING,\n cloudGraphHostName:\n cacheRecord.account?.cloudGraphHostName ||\n Constants.EMPTY_STRING,\n msGraphHost:\n cacheRecord.account?.msGraphHost || Constants.EMPTY_STRING,\n code: serverTokenResponse?.spa_code,\n fromNativeBroker: false,\n };\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseClient } from \"./BaseClient\";\nimport { CommonAuthorizationUrlRequest } from \"../request/CommonAuthorizationUrlRequest\";\nimport { CommonAuthorizationCodeRequest } from \"../request/CommonAuthorizationCodeRequest\";\nimport { Authority } from \"../authority/Authority\";\nimport { RequestParameterBuilder } from \"../request/RequestParameterBuilder\";\nimport {\n GrantType,\n AuthenticationScheme,\n PromptValue,\n Separators,\n AADServerParamKeys,\n HeaderNames,\n} from \"../utils/Constants\";\nimport {\n ClientConfiguration,\n isOidcProtocolMode,\n} from \"../config/ClientConfiguration\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse\";\nimport { NetworkResponse } from \"../network/NetworkManager\";\nimport { ResponseHandler } from \"../response/ResponseHandler\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult\";\nimport { StringUtils } from \"../utils/StringUtils\";\nimport { ClientAuthError } from \"../error/ClientAuthError\";\nimport { UrlString } from \"../url/UrlString\";\nimport { ServerAuthorizationCodeResponse } from \"../response/ServerAuthorizationCodeResponse\";\nimport { CommonEndSessionRequest } from \"../request/CommonEndSessionRequest\";\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator\";\nimport { RequestThumbprint } from \"../network/RequestThumbprint\";\nimport { AuthorizationCodePayload } from \"../response/AuthorizationCodePayload\";\nimport { TimeUtils } from \"../utils/TimeUtils\";\nimport { AccountInfo } from \"../account/AccountInfo\";\nimport {\n buildClientInfoFromHomeAccountId,\n buildClientInfo,\n} from \"../account/ClientInfo\";\nimport { CcsCredentialType, CcsCredential } from \"../account/CcsCredential\";\nimport { ClientConfigurationError } from \"../error/ClientConfigurationError\";\nimport { RequestValidator } from \"../request/RequestValidator\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent\";\nimport { invokeAsync } from \"../utils/FunctionWrappers\";\n\n/**\n * Oauth2.0 Authorization Code client\n * @internal\n */\nexport class AuthorizationCodeClient extends BaseClient {\n // Flag to indicate if client is for hybrid spa auth code redemption\n protected includeRedirectUri: boolean = true;\n private oidcDefaultScopes;\n\n constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n super(configuration, performanceClient);\n this.oidcDefaultScopes =\n this.config.authOptions.authority.options.OIDCOptions?.defaultScopes;\n }\n\n /**\n * Creates the URL of the authorization request letting the user input credentials and consent to the\n * application. The URL target the /authorize endpoint of the authority configured in the\n * application object.\n *\n * Once the user inputs their credentials and consents, the authority will send a response to the redirect URI\n * sent in the request and should contain an authorization code, which can then be used to acquire tokens via\n * acquireToken(AuthorizationCodeRequest)\n * @param request\n */\n async getAuthCodeUrl(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.GetAuthCodeUrl,\n request.correlationId\n );\n\n const queryString = await invokeAsync(\n this.createAuthCodeUrlQueryString.bind(this),\n PerformanceEvents.AuthClientCreateQueryString,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request);\n\n return UrlString.appendQueryString(\n this.authority.authorizationEndpoint,\n queryString\n );\n }\n\n /**\n * API to acquire a token in exchange of 'authorization_code` acquired by the user in the first leg of the\n * authorization_code_grant\n * @param request\n */\n async acquireToken(\n request: CommonAuthorizationCodeRequest,\n authCodePayload?: AuthorizationCodePayload\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientAcquireToken,\n request.correlationId\n );\n\n if (!request.code) {\n throw ClientAuthError.createTokenRequestCannotBeMadeError();\n }\n\n const reqTimestamp = TimeUtils.nowSeconds();\n const response = await invokeAsync(\n this.executeTokenRequest.bind(this),\n PerformanceEvents.AuthClientExecuteTokenRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(this.authority, request);\n\n // Retrieve requestId from response headers\n const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];\n\n const responseHandler = new ResponseHandler(\n this.config.authOptions.clientId,\n this.cacheManager,\n this.cryptoUtils,\n this.logger,\n this.config.serializableCache,\n this.config.persistencePlugin,\n this.performanceClient\n );\n\n // Validate response. This function throws a server error if an error is returned by the server.\n responseHandler.validateTokenResponse(response.body);\n\n return invokeAsync(\n responseHandler.handleServerTokenResponse.bind(responseHandler),\n PerformanceEvents.HandleServerTokenResponse,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n response.body,\n this.authority,\n reqTimestamp,\n request,\n authCodePayload,\n undefined,\n undefined,\n undefined,\n requestId\n );\n }\n\n /**\n * Handles the hash fragment response from public client code request. Returns a code response used by\n * the client to exchange for a token in acquireToken.\n * @param hashFragment\n */\n handleFragmentResponse(\n hashFragment: string,\n cachedState: string\n ): AuthorizationCodePayload {\n // Handle responses.\n const responseHandler = new ResponseHandler(\n this.config.authOptions.clientId,\n this.cacheManager,\n this.cryptoUtils,\n this.logger,\n null,\n null\n );\n\n const serverParams: ServerAuthorizationCodeResponse =\n UrlString.getDeserializedCodeResponse(\n this.config.authOptions.authority.options.OIDCOptions\n ?.serverResponseType,\n hashFragment\n );\n\n // Get code response\n responseHandler.validateServerAuthorizationCodeResponse(\n serverParams,\n cachedState,\n this.cryptoUtils\n );\n\n // throw when there is no auth code in the response\n if (!serverParams.code) {\n throw ClientAuthError.createNoAuthCodeInServerResponseError();\n }\n return {\n ...serverParams,\n // Code param is optional in ServerAuthorizationCodeResponse but required in AuthorizationCodePaylod\n code: serverParams.code,\n };\n }\n\n /**\n * Used to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param authorityUri\n */\n getLogoutUri(logoutRequest: CommonEndSessionRequest): string {\n // Throw error if logoutRequest is null/undefined\n if (!logoutRequest) {\n throw ClientConfigurationError.createEmptyLogoutRequestError();\n }\n const queryString = this.createLogoutUrlQueryString(logoutRequest);\n\n // Construct logout URI\n return UrlString.appendQueryString(\n this.authority.endSessionEndpoint,\n queryString\n );\n }\n\n /**\n * Executes POST request to token endpoint\n * @param authority\n * @param request\n */\n private async executeTokenRequest(\n authority: Authority,\n request: CommonAuthorizationCodeRequest\n ): Promise> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientExecuteTokenRequest,\n request.correlationId\n );\n\n const queryParametersString = this.createTokenQueryParameters(request);\n const endpoint = UrlString.appendQueryString(\n authority.tokenEndpoint,\n queryParametersString\n );\n\n const requestBody = await invokeAsync(\n this.createTokenRequestBody.bind(this),\n PerformanceEvents.AuthClientCreateTokenRequestBody,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request);\n\n let ccsCredential: CcsCredential | undefined = undefined;\n if (request.clientInfo) {\n try {\n const clientInfo = buildClientInfo(\n request.clientInfo,\n this.cryptoUtils\n );\n ccsCredential = {\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n } catch (e) {\n this.logger.verbose(\n \"Could not parse client info for CCS Header: \" + e\n );\n }\n }\n const headers: Record = this.createTokenRequestHeaders(\n ccsCredential || request.ccsCredential\n );\n\n const thumbprint: RequestThumbprint = {\n clientId: this.config.authOptions.clientId,\n authority: authority.canonicalAuthority,\n scopes: request.scopes,\n claims: request.claims,\n authenticationScheme: request.authenticationScheme,\n resourceRequestMethod: request.resourceRequestMethod,\n resourceRequestUri: request.resourceRequestUri,\n shrClaims: request.shrClaims,\n sshKid: request.sshKid,\n };\n\n return invokeAsync(\n this.executePostToTokenEndpoint.bind(this),\n PerformanceEvents.BaseClientExecutePostToTokenEndpoint,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(endpoint, requestBody, headers, thumbprint, request.correlationId);\n }\n\n /**\n * Generates a map for all the params to be sent to the service\n * @param request\n */\n private async createTokenRequestBody(\n request: CommonAuthorizationCodeRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientCreateTokenRequestBody,\n request.correlationId\n );\n\n const parameterBuilder = new RequestParameterBuilder();\n\n parameterBuilder.addClientId(\n request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||\n this.config.authOptions.clientId\n );\n\n /*\n * For hybrid spa flow, there will be a code but no verifier\n * In this scenario, don't include redirect uri as auth code will not be bound to redirect URI\n */\n if (!this.includeRedirectUri) {\n // Just validate\n RequestValidator.validateRedirectUri(request.redirectUri);\n } else {\n // Validate and include redirect uri\n parameterBuilder.addRedirectUri(request.redirectUri);\n }\n\n // Add scope array, parameter builder will add default scopes and dedupe\n parameterBuilder.addScopes(\n request.scopes,\n true,\n this.oidcDefaultScopes\n );\n\n // add code: user set, not validated\n parameterBuilder.addAuthorizationCode(request.code);\n\n // Add library metadata\n parameterBuilder.addLibraryInfo(this.config.libraryInfo);\n parameterBuilder.addApplicationTelemetry(\n this.config.telemetry.application\n );\n parameterBuilder.addThrottling();\n\n if (this.serverTelemetryManager && !isOidcProtocolMode(this.config)) {\n parameterBuilder.addServerTelemetry(this.serverTelemetryManager);\n }\n\n // add code_verifier if passed\n if (request.codeVerifier) {\n parameterBuilder.addCodeVerifier(request.codeVerifier);\n }\n\n if (this.config.clientCredentials.clientSecret) {\n parameterBuilder.addClientSecret(\n this.config.clientCredentials.clientSecret\n );\n }\n\n if (this.config.clientCredentials.clientAssertion) {\n const clientAssertion =\n this.config.clientCredentials.clientAssertion;\n parameterBuilder.addClientAssertion(clientAssertion.assertion);\n parameterBuilder.addClientAssertionType(\n clientAssertion.assertionType\n );\n }\n\n parameterBuilder.addGrantType(GrantType.AUTHORIZATION_CODE_GRANT);\n parameterBuilder.addClientInfo();\n\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n const popTokenGenerator = new PopTokenGenerator(\n this.cryptoUtils,\n this.performanceClient\n );\n\n this.performanceClient?.setPreQueueTime(\n PerformanceEvents.PopTokenGenerateCnf,\n request.correlationId\n );\n const reqCnfData = await popTokenGenerator.generateCnf(request);\n // SPA PoP requires full Base64Url encoded req_cnf string (unhashed)\n parameterBuilder.addPopToken(reqCnfData.reqCnfString);\n } else if (request.authenticationScheme === AuthenticationScheme.SSH) {\n if (request.sshJwk) {\n parameterBuilder.addSshJwk(request.sshJwk);\n } else {\n throw ClientConfigurationError.createMissingSshJwkError();\n }\n }\n\n const correlationId =\n request.correlationId ||\n this.config.cryptoInterface.createNewGuid();\n parameterBuilder.addCorrelationId(correlationId);\n\n if (\n !StringUtils.isEmptyObj(request.claims) ||\n (this.config.authOptions.clientCapabilities &&\n this.config.authOptions.clientCapabilities.length > 0)\n ) {\n parameterBuilder.addClaims(\n request.claims,\n this.config.authOptions.clientCapabilities\n );\n }\n\n let ccsCred: CcsCredential | undefined = undefined;\n if (request.clientInfo) {\n try {\n const clientInfo = buildClientInfo(\n request.clientInfo,\n this.cryptoUtils\n );\n ccsCred = {\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n } catch (e) {\n this.logger.verbose(\n \"Could not parse client info for CCS Header: \" + e\n );\n }\n } else {\n ccsCred = request.ccsCredential;\n }\n\n // Adds these as parameters in the request instead of headers to prevent CORS preflight request\n if (this.config.systemOptions.preventCorsPreflight && ccsCred) {\n switch (ccsCred.type) {\n case CcsCredentialType.HOME_ACCOUNT_ID:\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n ccsCred.credential\n );\n parameterBuilder.addCcsOid(clientInfo);\n } catch (e) {\n this.logger.verbose(\n \"Could not parse home account ID for CCS Header: \" +\n e\n );\n }\n break;\n case CcsCredentialType.UPN:\n parameterBuilder.addCcsUpn(ccsCred.credential);\n break;\n }\n }\n\n if (request.tokenBodyParameters) {\n parameterBuilder.addExtraQueryParameters(\n request.tokenBodyParameters\n );\n }\n\n // Add hybrid spa parameters if not already provided\n if (\n request.enableSpaAuthorizationCode &&\n (!request.tokenBodyParameters ||\n !request.tokenBodyParameters[\n AADServerParamKeys.RETURN_SPA_CODE\n ])\n ) {\n parameterBuilder.addExtraQueryParameters({\n [AADServerParamKeys.RETURN_SPA_CODE]: \"1\",\n });\n }\n\n return parameterBuilder.createQueryString();\n }\n\n /**\n * This API validates the `AuthorizationCodeUrlRequest` and creates a URL\n * @param request\n */\n private async createAuthCodeUrlQueryString(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientCreateQueryString,\n request.correlationId\n );\n\n const parameterBuilder = new RequestParameterBuilder();\n\n parameterBuilder.addClientId(\n request.extraQueryParameters?.[AADServerParamKeys.CLIENT_ID] ||\n this.config.authOptions.clientId\n );\n\n const requestScopes = [\n ...(request.scopes || []),\n ...(request.extraScopesToConsent || []),\n ];\n parameterBuilder.addScopes(requestScopes, true, this.oidcDefaultScopes);\n\n // validate the redirectUri (to be a non null value)\n parameterBuilder.addRedirectUri(request.redirectUri);\n\n // generate the correlationId if not set by the user and add\n const correlationId =\n request.correlationId ||\n this.config.cryptoInterface.createNewGuid();\n parameterBuilder.addCorrelationId(correlationId);\n\n // add response_mode. If not passed in it defaults to query.\n parameterBuilder.addResponseMode(request.responseMode);\n\n // add response_type = code\n parameterBuilder.addResponseTypeCode();\n\n // add library info parameters\n parameterBuilder.addLibraryInfo(this.config.libraryInfo);\n if (!isOidcProtocolMode(this.config)) {\n parameterBuilder.addApplicationTelemetry(\n this.config.telemetry.application\n );\n }\n\n // add client_info=1\n parameterBuilder.addClientInfo();\n\n if (request.codeChallenge && request.codeChallengeMethod) {\n parameterBuilder.addCodeChallengeParams(\n request.codeChallenge,\n request.codeChallengeMethod\n );\n }\n\n if (request.prompt) {\n parameterBuilder.addPrompt(request.prompt);\n }\n\n if (request.domainHint) {\n parameterBuilder.addDomainHint(request.domainHint);\n }\n\n // Add sid or loginHint with preference for login_hint claim (in request) -> sid -> loginHint (upn/email) -> username of AccountInfo object\n if (request.prompt !== PromptValue.SELECT_ACCOUNT) {\n // AAD will throw if prompt=select_account is passed with an account hint\n if (request.sid && request.prompt === PromptValue.NONE) {\n // SessionID is only used in silent calls\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from request\"\n );\n parameterBuilder.addSid(request.sid);\n } else if (request.account) {\n const accountSid = this.extractAccountSid(request.account);\n const accountLoginHintClaim = this.extractLoginHint(\n request.account\n );\n // If login_hint claim is present, use it over sid/username\n if (accountLoginHintClaim) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: login_hint claim present on account\"\n );\n parameterBuilder.addLoginHint(accountLoginHintClaim);\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n parameterBuilder.addCcsOid(clientInfo);\n } catch (e) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n } else if (accountSid && request.prompt === PromptValue.NONE) {\n /*\n * If account and loginHint are provided, we will check account first for sid before adding loginHint\n * SessionId is only used in silent calls\n */\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from account\"\n );\n parameterBuilder.addSid(accountSid);\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n parameterBuilder.addCcsOid(clientInfo);\n } catch (e) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n } else if (request.loginHint) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Adding login_hint from request\"\n );\n parameterBuilder.addLoginHint(request.loginHint);\n parameterBuilder.addCcsUpn(request.loginHint);\n } else if (request.account.username) {\n // Fallback to account username if provided\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Adding login_hint from account\"\n );\n parameterBuilder.addLoginHint(request.account.username);\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n parameterBuilder.addCcsOid(clientInfo);\n } catch (e) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n }\n } else if (request.loginHint) {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: No account, adding login_hint from request\"\n );\n parameterBuilder.addLoginHint(request.loginHint);\n parameterBuilder.addCcsUpn(request.loginHint);\n }\n } else {\n this.logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is select_account, ignoring account hints\"\n );\n }\n\n if (request.nonce) {\n parameterBuilder.addNonce(request.nonce);\n }\n\n if (request.state) {\n parameterBuilder.addState(request.state);\n }\n\n if (\n request.claims ||\n (this.config.authOptions.clientCapabilities &&\n this.config.authOptions.clientCapabilities.length > 0)\n ) {\n parameterBuilder.addClaims(\n request.claims,\n this.config.authOptions.clientCapabilities\n );\n }\n\n if (request.extraQueryParameters) {\n parameterBuilder.addExtraQueryParameters(\n request.extraQueryParameters\n );\n }\n\n if (request.nativeBroker) {\n // signal ests that this is a WAM call\n parameterBuilder.addNativeBroker();\n\n // pass the req_cnf for POP\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n const popTokenGenerator = new PopTokenGenerator(\n this.cryptoUtils\n );\n // to reduce the URL length, it is recommended to send the hash of the req_cnf instead of the whole string\n const reqCnfData = await popTokenGenerator.generateCnf(request);\n parameterBuilder.addPopToken(reqCnfData.reqCnfHash);\n }\n }\n\n return parameterBuilder.createQueryString();\n }\n\n /**\n * This API validates the `EndSessionRequest` and creates a URL\n * @param request\n */\n private createLogoutUrlQueryString(\n request: CommonEndSessionRequest\n ): string {\n const parameterBuilder = new RequestParameterBuilder();\n\n if (request.postLogoutRedirectUri) {\n parameterBuilder.addPostLogoutRedirectUri(\n request.postLogoutRedirectUri\n );\n }\n\n if (request.correlationId) {\n parameterBuilder.addCorrelationId(request.correlationId);\n }\n\n if (request.idTokenHint) {\n parameterBuilder.addIdTokenHint(request.idTokenHint);\n }\n\n if (request.state) {\n parameterBuilder.addState(request.state);\n }\n\n if (request.logoutHint) {\n parameterBuilder.addLogoutHint(request.logoutHint);\n }\n\n if (request.extraQueryParameters) {\n parameterBuilder.addExtraQueryParameters(\n request.extraQueryParameters\n );\n }\n\n return parameterBuilder.createQueryString();\n }\n\n /**\n * Helper to get sid from account. Returns null if idTokenClaims are not present or sid is not present.\n * @param account\n */\n private extractAccountSid(account: AccountInfo): string | null {\n return account.idTokenClaims?.sid || null;\n }\n\n private extractLoginHint(account: AccountInfo): string | null {\n return account.idTokenClaims?.login_hint || null;\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Tenant Discovery Response which contains the relevant OAuth endpoints and data needed for authentication and authorization.\n */\nexport type OpenIdConfigResponse = {\n authorization_endpoint: string;\n token_endpoint: string;\n end_session_endpoint?: string;\n issuer: string;\n jwks_uri: string;\n};\n\nexport function isOpenIdConfigResponse(response: object): boolean {\n return (\n response.hasOwnProperty(\"authorization_endpoint\") &&\n response.hasOwnProperty(\"token_endpoint\") &&\n response.hasOwnProperty(\"issuer\") &&\n response.hasOwnProperty(\"jwks_uri\")\n );\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const rawMetdataJSON = {\n endpointMetadata: {\n \"https://login.microsoftonline.com/common/\": {\n token_endpoint:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.com/common/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.com/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.com/common/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.com\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pas.windows.net\",\n },\n \"https://login.chinacloudapi.cn/common/\": {\n token_endpoint:\n \"https://login.chinacloudapi.cn/common/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.chinacloudapi.cn/common/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.partner.microsoftonline.cn/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint:\n \"https://microsoftgraph.chinacloudapi.cn/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.chinacloudapi.cn/common/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.chinacloudapi.cn/common/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint: \"https://login.chinacloudapi.cn/common/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"partner.microsoftonline.cn\",\n cloud_graph_host_name: \"graph.chinacloudapi.cn\",\n msgraph_host: \"microsoftgraph.chinacloudapi.cn\",\n rbac_url: \"https://pas.chinacloudapi.cn\",\n },\n \"https://login.microsoftonline.us/common/\": {\n token_endpoint:\n \"https://login.microsoftonline.us/common/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.us/common/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.us/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.us/common/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.us/common/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.us/common/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.us/common/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.us\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pasff.usgovcloudapi.net\",\n },\n \"https://login.microsoftonline.com/consumers/\": {\n token_endpoint:\n \"https://login.microsoftonline.com/consumers/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.com/consumers/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.com/consumers/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.com/consumers/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.com\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pas.windows.net\",\n },\n \"https://login.chinacloudapi.cn/consumers/\": {\n token_endpoint:\n \"https://login.chinacloudapi.cn/consumers/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.chinacloudapi.cn/consumers/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.partner.microsoftonline.cn/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint:\n \"https://microsoftgraph.chinacloudapi.cn/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.chinacloudapi.cn/consumers/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.chinacloudapi.cn/consumers/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.chinacloudapi.cn/consumers/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.chinacloudapi.cn/consumers/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"partner.microsoftonline.cn\",\n cloud_graph_host_name: \"graph.chinacloudapi.cn\",\n msgraph_host: \"microsoftgraph.chinacloudapi.cn\",\n rbac_url: \"https://pas.chinacloudapi.cn\",\n },\n \"https://login.microsoftonline.us/consumers/\": {\n token_endpoint:\n \"https://login.microsoftonline.us/consumers/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.us/consumers/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.us/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.us/consumers/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.us/consumers/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.us/consumers/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.us/consumers/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.us\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pasff.usgovcloudapi.net\",\n },\n \"https://login.microsoftonline.com/organizations/\": {\n token_endpoint:\n \"https://login.microsoftonline.com/organizations/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.com/organizations/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.com/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.com/organizations/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.com/organizations/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.com\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pas.windows.net\",\n },\n \"https://login.chinacloudapi.cn/organizations/\": {\n token_endpoint:\n \"https://login.chinacloudapi.cn/organizations/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.chinacloudapi.cn/organizations/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.partner.microsoftonline.cn/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint:\n \"https://microsoftgraph.chinacloudapi.cn/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.chinacloudapi.cn/organizations/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.chinacloudapi.cn/organizations/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.chinacloudapi.cn/organizations/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.chinacloudapi.cn/organizations/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"partner.microsoftonline.cn\",\n cloud_graph_host_name: \"graph.chinacloudapi.cn\",\n msgraph_host: \"microsoftgraph.chinacloudapi.cn\",\n rbac_url: \"https://pas.chinacloudapi.cn\",\n },\n \"https://login.microsoftonline.us/organizations/\": {\n token_endpoint:\n \"https://login.microsoftonline.us/organizations/oauth2/v2.0/token\",\n token_endpoint_auth_methods_supported: [\n \"client_secret_post\",\n \"private_key_jwt\",\n \"client_secret_basic\",\n ],\n jwks_uri:\n \"https://login.microsoftonline.us/organizations/discovery/v2.0/keys\",\n response_modes_supported: [\"query\", \"fragment\", \"form_post\"],\n subject_types_supported: [\"pairwise\"],\n id_token_signing_alg_values_supported: [\"RS256\"],\n response_types_supported: [\n \"code\",\n \"id_token\",\n \"code id_token\",\n \"id_token token\",\n ],\n scopes_supported: [\"openid\", \"profile\", \"email\", \"offline_access\"],\n issuer: \"https://login.microsoftonline.us/{tenantid}/v2.0\",\n request_uri_parameter_supported: false,\n userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\",\n authorization_endpoint:\n \"https://login.microsoftonline.us/organizations/oauth2/v2.0/authorize\",\n device_authorization_endpoint:\n \"https://login.microsoftonline.us/organizations/oauth2/v2.0/devicecode\",\n http_logout_supported: true,\n frontchannel_logout_supported: true,\n end_session_endpoint:\n \"https://login.microsoftonline.us/organizations/oauth2/v2.0/logout\",\n claims_supported: [\n \"sub\",\n \"iss\",\n \"cloud_instance_name\",\n \"cloud_instance_host_name\",\n \"cloud_graph_host_name\",\n \"msgraph_host\",\n \"aud\",\n \"exp\",\n \"iat\",\n \"auth_time\",\n \"acr\",\n \"nonce\",\n \"preferred_username\",\n \"name\",\n \"tid\",\n \"ver\",\n \"at_hash\",\n \"c_hash\",\n \"email\",\n ],\n kerberos_endpoint:\n \"https://login.microsoftonline.us/organizations/kerberos\",\n tenant_region_scope: null,\n cloud_instance_name: \"microsoftonline.us\",\n cloud_graph_host_name: \"graph.windows.net\",\n msgraph_host: \"graph.microsoft.com\",\n rbac_url: \"https://pasff.usgovcloudapi.net\",\n },\n },\n instanceDiscoveryMetadata: {\n \"https://login.microsoftonline.com/common/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.chinacloudapi.cn/common/\": {\n tenant_discovery_endpoint:\n \"https://login.chinacloudapi.cn/common/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.microsoftonline.us/common/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.us/common/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.microsoftonline.com/consumers/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.com/consumers/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.chinacloudapi.cn/consumers/\": {\n tenant_discovery_endpoint:\n \"https://login.chinacloudapi.cn/consumers/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.microsoftonline.us/consumers/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.us/consumers/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.microsoftonline.com/organizations/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.chinacloudapi.cn/organizations/\": {\n tenant_discovery_endpoint:\n \"https://login.chinacloudapi.cn/organizations/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n \"https://login.microsoftonline.us/organizations/\": {\n tenant_discovery_endpoint:\n \"https://login.microsoftonline.us/organizations/v2.0/.well-known/openid-configuration\",\n \"api-version\": \"1.1\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n },\n};\n\nexport const EndpointMetadata = rawMetdataJSON.endpointMetadata;\nexport const InstanceDiscoveryMetadata =\n rawMetdataJSON.instanceDiscoveryMetadata;\n\nexport const InstanceDiscoveryMetadataAliases: Set = new Set();\nfor (const key in InstanceDiscoveryMetadata) {\n for (const metadata of InstanceDiscoveryMetadata[key].metadata) {\n for (const alias of metadata.aliases) {\n InstanceDiscoveryMetadataAliases.add(alias);\n }\n }\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata\";\n\n/**\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\n */\nexport type CloudInstanceDiscoveryResponse = {\n tenant_discovery_endpoint: string;\n metadata: Array;\n};\n\nexport function isCloudInstanceDiscoveryResponse(response: object): boolean {\n return (\n response.hasOwnProperty(\"tenant_discovery_endpoint\") &&\n response.hasOwnProperty(\"metadata\")\n );\n}\n","/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\n */\nexport type CloudInstanceDiscoveryErrorResponse = {\n error: String;\n error_description: String;\n error_codes?: Array