diff --git a/README.md b/README.md index 87ebb04..07fd23e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # App Auth JS Helper -Wrapper for [AppAuthJS](https://www.npmjs.com/package/@openid/appauth) to assist with the full OAuth2 / OIDC token life-cycle. +Wrapper for [AppAuthJS](https://www.npmjs.com/package/@openid/appauth) to assist with the full OAuth2 / OIDC token life-cycle in a SPA setting. ## Purpose The primary goal of both AppAuth and this helper is to allow your single-page application to obtain OAuth2 access tokens and OpenID Connect id tokens. AppAuth for JavaScript provides an SDK for performing a PKCE-based Authorization Code flow within a JavaScript-based application. It is designed to be the generic underlying library for any type of JS app - not necessarily browser-based single-paged applications. The specific patterns for how you would use it within a single-page application are therefore not very clear. The goal of this helper library is to make that specific integration much easier. -There are several aspects that this helper aims to add on top of AppAuth: +There are several aspects that this helper aims to add on top of AppAuth-JS: - **Simpler application integration** - **Silent token acquisition** @@ -45,9 +45,9 @@ In the case when your request fails because the access token has expired, the id > request a new access token and retry the protected resource > request. -Thanks to the identity proxy, you won't have to worry about implementing this retry logic yourself. Just make the calls to your APIs and let the proxy handle the tokens. For more details on how the identity proxy accomplishes this, review this article: [Service Workers as an Identity Proxy](./service_workers.md). +Thanks to the identity proxy, you won't have to worry about implementing this retry logic yourself. Just make the calls to your APIs and let the proxy handle the tokens - your code won't even be aware of the renewals going on behind the scenes. For more details on how the identity proxy accomplishes this, review this article: [Service Workers as an Identity Proxy](./service_workers.md). -AppAuthHelper has two ways to renew an expired access token: a silent authorization code grant (the default behavior), or a refresh token grant. If this happens while the user still has a valid session within the OP (and the OP no longer prompts for consent), a new access token can be silently obtained by initiating a new authorization code grant within a hidden iframe. If you do not want your RP to depend on an active session within the OP (or if the OP requires consent for each authorization code grant) then you can tell AppAuthHelper to use a refresh token grant instead. Be sure the OP has been configured to allow this RP to use the refresh token grant if you choose this option. +AppAuthHelper has two ways to renew an expired access token: a silent authorization code grant (the default behavior), or a refresh token grant. If token expiration happens while the user still has a valid session within the OP (and the OP no longer prompts for consent), a new access token can be silently obtained by initiating a new authorization code grant within a hidden iframe. If you do not want your RP to depend on an active session within the OP (or if the OP requires consent for each authorization code grant) then you can tell AppAuthHelper to use a refresh token grant instead. Be sure the OP has been configured to allow this RP to use the refresh token grant if you choose this option. ## Using this library @@ -87,10 +87,20 @@ Once the library is loaded, you have to provide the environmental details along // this assumes that 'loginIframe' is an iframe that has already been mounted to the DOM }, - tokensAvailableHandler: function (claims) { + tokensAvailableHandler: function (claims, id_token, interactively_logged_in) { // This is a great place to startup the parts of your SPA that are for logged-in users. + // The "claims" parameter is the content of the id_token, which tells you useful details - // about the logged-in user. + // about the logged-in user. It will be undefined if you aren't using OIDC. + + // The "id_token" is the actual id_token value, which can be useful to have in its original form + // for various use-cases; OP-based session management may be one such case. + // See the companion library "oidcsessioncheck" for further details. + + // The "interactively_logged_in" parameter is a boolean; it lets your app know that tokens + // are available because the user just returned from the OP (rather than reading them from browser + // storage). This may be useful in some circumstances for user-experience concerns; for example, + // you should take care to avoid looping redirections between the OP and RP by checking this value. // At this point your application code can start making network calls to the resource servers // you have configured, above. @@ -118,7 +128,7 @@ Once the library is loaded, you have to provide the environmental details along - extras - Optional simple map of additional key=value pairs you would like to pass to the authorization endpoint. - tokensAvailableHandler - function to be called when tokens are first available - interactionRequiredHandler - optional function to be called when the user needs to interact with the OP; for example, to log in. - - renewCooldownPeriod [default: 1] - Minimum time (in seconds) between requests to the authorizationEndpoint for token renewal attempts + - renewCooldownPeriod [default: 1] - Minimum time (in seconds) between requests to the OP for token renewal attempts - oidc [default: true] - indicate whether or not you want to get back an id_token - identityProxyPreference [default: serviceWorker] - Preferred identity proxy implementation (serviceWorker or XHR) - renewStrategy [default: authCode] - Preferred method for obtaining fresh (and down-scoped) access tokens (authCode or refreshToken); see "How it works" for details. @@ -141,11 +151,16 @@ If you don't want the default behavior of redirecting your users to the authoriz *Logging Out:* - AppAuthHelper.logout().then(function () { + AppAuthHelper.logout({ + revoke_tokens: true, + end_session: true + }).then(function () { // whatever your application should do after the tokens are removed }); -Calling `AppAuthHelper.logout()` will trigger calls to both the access token revocation endpoint, as well as the id token end session endpoint. When both of those have completed, the tokens are removed from browser storage. A promise is returned from `logout()`; use `.then()` to do whatever is appropriate for your application after the session is terminated. +Calling `AppAuthHelper.logout(options)` can trigger calls to both the access token revocation endpoint, as well as the id token end session endpoint. By default, it will revoke all access tokens (and if present, the refresh token) and it will call the end session endpoint if there is an id_token available to pass it. If you don't want to revoke tokens or end the OP session as part of logout, you can override this behavior by setting the appropriate option to `false`. Regardless of the options provided, after that process completes the tokens are removed from browser storage. A promise is returned from `logout()`; use `.then()` to do whatever is appropriate for your application after the session is terminated. + +You may want to consider setting `end_session: false` if you are calling `logout` in response to an OIDC session check failure (see [oidcSessionCheck](https://github.com/ForgeRock/oidcSessionCheck) for an example of such a case). The session check failure could be due to browser restrictions on third-party cookies, so you may be able to recover from this type of failure by performing a full-page redirection so long as you don't actively try to terminate the OP session first. ### Using Tokens @@ -216,4 +231,4 @@ AppAuthHelper was developed by ForgeRock, Inc. Please file issues and open pull ## License -Apache 2.0. Portions Copyright ForgeRock, Inc. 2018-2019 +Apache 2.0. Portions Copyright ForgeRock, Inc. 2018-2021 diff --git a/TokenManager.js b/TokenManager.js index 761a610..f4ed6d1 100644 --- a/TokenManager.js +++ b/TokenManager.js @@ -361,20 +361,20 @@ } return headersObj; }, - logout: function () { + logout: function (options) { return this.fetchTokensFromIndexedDB().then((function (tokens) { if (!tokens) { return; } var revokeRequests = []; - if (tokens.accessToken) { + if (options.revoke_tokens && tokens.accessToken) { revokeRequests.push(new AppAuth.RevokeTokenRequest({ client_id: this.appAuthConfig.clientId, token_type_hint: "access_token", token: tokens.accessToken })); } - if (tokens.refreshToken) { + if (options.revoke_tokens && tokens.refreshToken) { revokeRequests.push(new AppAuth.RevokeTokenRequest({ client_id: this.appAuthConfig.clientId, token_type_hint: "refresh_token", @@ -384,7 +384,7 @@ return Promise.all( revokeRequests.concat( Object.keys(this.appAuthConfig.resourceServers) - .filter(function (rs) { return !!tokens[rs]; }) + .filter(function (rs) { return options.revoke_tokens && !!tokens[rs]; }) .map((function (rs) { return new AppAuth.RevokeTokenRequest({ client_id: this.appAuthConfig.clientId, @@ -399,7 +399,7 @@ ); }).bind(this)) ).then((function () { - if (this.appAuthConfig.oidc && tokens.idToken && this.client.configuration.endSessionEndpoint) { + if (options.end_session && this.appAuthConfig.oidc && tokens.idToken && this.client.configuration.endSessionEndpoint) { return fetch(this.client.configuration.endSessionEndpoint + "?id_token_hint=" + tokens.idToken); } else { return; diff --git a/appAuthHelper.js b/appAuthHelper.js index deb87a4..ebf6fc8 100644 --- a/appAuthHelper.js +++ b/appAuthHelper.js @@ -19,7 +19,7 @@ * @param {object} config.resourceServers - Map of resource server urls to the scopes which they require. Map values are space-delimited list of scopes requested by this RP for use with this RS * @param {object} [config.extras] -Additional parameters to include in the authorization request * @param {function} [config.interactionRequiredHandler] - optional function to be called anytime interaction is required. When not provided, default behavior is to redirect the current window to the authorizationEndpoint - * @param {function} config.tokensAvailableHandler - function to be called every time tokens are available - both initially and upon renewal + * @param {function} config.tokensAvailableHandler - function to be called once tokens are available - either from the browser storage or newly fetched. * @param {number} [config.renewCooldownPeriod=1] - Minimum time (in seconds) between requests to the authorizationEndpoint for token renewal attempts * @param {string} [config.redirectUri=appAuthHelperRedirect.html] - The redirect uri registered in the OP * @param {string} [config.serviceWorkerUri=appAuthServiceWorker.js] - The path to the service worker script @@ -37,7 +37,8 @@ this.renewCooldownPeriod = config.renewCooldownPeriod || 1; this.appAuthConfig = { - appLocation: document.location.href + // discard the &loggedin=true part that might be included by us + appLocation: document.location.href.replace(/#?&loggedin=true$/, "") }; this.tokensAvailableHandler = config.tokensAvailableHandler; this.interactionRequiredHandler = config.interactionRequiredHandler; @@ -88,12 +89,6 @@ } switch (e.data.message) { case "appAuth-tokensAvailable": - var originalWindowHash = localStorage.getItem("originalWindowHash-" + this.appAuthConfig.clientId); - if (originalWindowHash !== null) { - window.location.hash = originalWindowHash; - localStorage.removeItem("originalWindowHash-" + this.appAuthConfig.clientId); - } - // this should only be set as part of token renewal if (e.data.resourceServer) { localStorage.removeItem("currentResourceServer"); @@ -105,9 +100,20 @@ this.identityProxy.tokensRenewed(e.data.resourceServer); } else { + var originalWindowHash = localStorage.getItem("originalWindowHash-" + this.appAuthConfig.clientId), + returnedFromLogin = !!window.location.hash.match(/&loggedin=true$/); + + if (originalWindowHash === null || originalWindowHash === "" || originalWindowHash === "#") { + history.replaceState(undefined, undefined, window.location.href.replace(/#&loggedin=true$/, "")); + } else { + history.replaceState(undefined, undefined, "#" + originalWindowHash.replace("#", "")); + } + + localStorage.removeItem("originalWindowHash-" + this.appAuthConfig.clientId); + this.registerIdentityProxy() .then((function () { - return this.tokensAvailableHandler(e.data.idTokenClaims, e.data.idToken); + return this.tokensAvailableHandler(e.data.idTokenClaims, e.data.idToken, returnedFromLogin); }).bind(this)); } @@ -118,11 +124,9 @@ } else { // Default behavior for when interaction is required is to redirect to the OP for login. - if (window.location.hash.replace("#","").length) { - // When interaction is required, the current hash state may be lost during redirection. - // Save it in localStorage so that it can be returned to upon successfully authenticating - localStorage.setItem("originalWindowHash-" + this.appAuthConfig.clientId, window.location.hash); - } + // When interaction is required, the current hash state may be lost during redirection. + // Save it in localStorage so that it can be returned to upon successfully authenticating + localStorage.setItem("originalWindowHash-" + this.appAuthConfig.clientId, window.location.hash); window.location.href = e.data.authorizationUrl; } @@ -209,12 +213,16 @@ * logout() will revoke the access token, use the id_token to end the session on the OP, clear them from the * local session, and finally notify the SPA that they are gone. */ - logout: function () { + logout: function (options) { + options = options || {}; + options.revoke_tokens = options.revoke_tokens!==false; + options.end_session = options.end_session!==false; return new Promise((function (resolve) { this.logoutComplete = resolve; this.appAuthIframe.contentWindow.postMessage({ message: "appAuth-logout", - config: this.appAuthConfig + config: this.appAuthConfig, + options: options }, this.iframeOrigin); }).bind(this)); }, diff --git a/appAuthHelperBundle.js b/appAuthHelperBundle.js index a9f6c8c..f1c14e3 100644 --- a/appAuthHelperBundle.js +++ b/appAuthHelperBundle.js @@ -43,4 +43,4 @@ License for AppAuthHelper (Apache 2.0) : Copyright (c) 2019 ForgeRock, Inc. */ -"use strict";function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}(function(a){if("object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.AppAuthHelper=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;carguments.length)&&h.call(arguments,1);return i[b]=!0,f(function(){i[b]&&(d?a.apply(null,d):a.call(null),c.clearImmediate(b))}),b},c.clearImmediate="function"==typeof d?d:function(a){delete i[a]}}).call(this,a("timers").setImmediate,a("timers").clearImmediate)},{"process/browser.js":5,timers:7}],8:[function(){(function(a){(function(a){var b=function checkIfIteratorIsSupported(){try{return!!Symbol.iterator}catch(a){return!1}}(),c=function(a){var c={next:function next(){var b=a.shift();return{done:void 0===b,value:b}}};return b&&(c[Symbol.iterator]=function(){return c}),c},d=function(a){return encodeURIComponent(a).replace(/%20/g,"+")},e=function(a){return decodeURIComponent((a+"").replace(/\+/g," "))};(function checkIfURLSearchParamsSupported(){try{var b=a.URLSearchParams;return"a=1"===new b("?a=1").toString()&&"function"==typeof b.prototype.set&&"function"==typeof b.prototype.entries}catch(a){return!1}})()||function polyfillURLSearchParams(){var e=function(a){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var b=_typeof(a);if("undefined"===b);else if("string"===b)""!==a&&this._fromString(a);else if(a instanceof e){var c=this;a.forEach(function(a,b){c.append(b,a)})}else if(!(null!==a&&"object"===b))throw new TypeError("Unsupported input's type for URLSearchParams");else if("[object Array]"===Object.prototype.toString.call(a)){for(var d,f=0;fa[0]?1:0}),a._entries&&(a._entries={});for(var c=0;carguments.length)&&h.call(arguments,1);return i[b]=!0,f(function(){i[b]&&(d?a.apply(null,d):a.call(null),c.clearImmediate(b))}),b},c.clearImmediate="function"==typeof d?d:function(a){delete i[a]}}).call(this,a("timers").setImmediate,a("timers").clearImmediate)},{"process/browser.js":5,timers:7}],8:[function(){(function(a){(function(a){var b=function checkIfIteratorIsSupported(){try{return!!Symbol.iterator}catch(a){return!1}}(),c=function(a){var c={next:function next(){var b=a.shift();return{done:void 0===b,value:b}}};return b&&(c[Symbol.iterator]=function(){return c}),c},d=function(a){return encodeURIComponent(a).replace(/%20/g,"+")},e=function(a){return decodeURIComponent((a+"").replace(/\+/g," "))};(function checkIfURLSearchParamsSupported(){try{var b=a.URLSearchParams;return"a=1"===new b("?a=1").toString()&&"function"==typeof b.prototype.set&&"function"==typeof b.prototype.entries}catch(a){return!1}})()||function polyfillURLSearchParams(){var e=function(a){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var b=_typeof(a);if("undefined"===b);else if("string"===b)""!==a&&this._fromString(a);else if(a instanceof e){var c=this;a.forEach(function(a,b){c.append(b,a)})}else if(!(null!==a&&"object"===b))throw new TypeError("Unsupported input's type for URLSearchParams");else if("[object Array]"===Object.prototype.toString.call(a)){for(var d,f=0;fa[0]?1:0}),a._entries&&(a._entries={});for(var c=0;c { // if we are running in the context of a full window (rather than an iframe) - if (!parent.document.getElementById('AppAuthIframe')) { + if (!parent.document.getElementById("AppAuthIframe")) { setTimeout(() => { var appLocation = document.createElement("a"); appLocation.href = appAuthConfig.appLocation || "."; + appLocation.hash = appLocation.hash + "&loggedin=true"; window.location.assign(appLocation.href); }, 0); } @@ -67,7 +68,7 @@ ); break; case "appAuth-logout": - tokenManager.logout().then(() => { + tokenManager.logout(e.data.options).then(() => { parent.postMessage({ message: "appAuth-logoutComplete" }, TRUSTED_ORIGIN); diff --git a/appAuthHelperFetchTokensBundle.js b/appAuthHelperFetchTokensBundle.js index 1572839..2011b06 100644 --- a/appAuthHelperFetchTokensBundle.js +++ b/appAuthHelperFetchTokensBundle.js @@ -43,4 +43,4 @@ License for AppAuthHelper (Apache 2.0) : Copyright (c) 2019 ForgeRock, Inc. */ -"use strict";function _typeof(e){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}(function(){function s(l,e,r){function t(d,n){if(!e[d]){if(!l[d]){var i="function"==typeof require&&require;if(!n&&i)return i(d,!0);if(o)return o(d,!0);var u=new Error("Cannot find module '"+d+"'");throw u.code="MODULE_NOT_FOUND",u}var a=e[d]={exports:{}};l[d][0].call(a.exports,function(e){var r=l[d][1][e];return t(r||e)},a,a.exports,s,l,e,r)}return e[d].exports}for(var o="function"==typeof require&&require,n=0;nr.BUILT_IN_PARAMETERS.indexOf(n)&&(o[n]=t.extras[n]);var a=this.utils.stringify(o),i=e.authorizationEndpoint;return i+"?"+a},e.prototype.completeAuthorizationRequestIfPossible=function(){var e=this;return o.log("Checking to see if there is an authorization response to be delivered."),this.notifier||o.log("Notifier is not present on AuthorizationRequest handler.\n No delivery of result will be possible"),this.completeAuthorizationRequest().then(function(t){t||o.log("No result is available yet."),t&&e.notifier&&e.notifier.onAuthorizationComplete(t.request,t.response,t.error)})},e.prototype.setAuthorizationNotifier=function(e){return this.notifier=e,this},e}();r.AuthorizationRequestHandler=a},{"./logger":12}],6:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var o=function(){function e(e){this.code=e.code,this.state=e.state}return e.prototype.toJson=function(){return{code:this.code,state:this.state}},e}();r.AuthorizationResponse=o;var n=function(){function e(e){this.error=e.error,this.errorDescription=e.error_description,this.errorUri=e.error_uri,this.state=e.state}return e.prototype.toJson=function(){return{error:this.error,error_description:this.errorDescription,error_uri:this.errorUri,state:this.state}},e}();r.AuthorizationError=n},{}],7:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var o=e("./xhr"),n=function(){function e(e){this.authorizationEndpoint=e.authorization_endpoint,this.tokenEndpoint=e.token_endpoint,this.revocationEndpoint=e.revocation_endpoint,this.userInfoEndpoint=e.userinfo_endpoint,this.endSessionEndpoint=e.end_session_endpoint}return e.prototype.toJson=function(){return{authorization_endpoint:this.authorizationEndpoint,token_endpoint:this.tokenEndpoint,revocation_endpoint:this.revocationEndpoint,end_session_endpoint:this.endSessionEndpoint,userinfo_endpoint:this.userInfoEndpoint}},e.fetchFromIssuer=function(t,r){var n=r||new o.JQueryRequestor;return n.xhr({url:t+"/"+".well-known"+"/"+"openid-configuration",dataType:"json",method:"GET"}).then(function(t){return new e(t)})},e}();r.AuthorizationServiceConfiguration=n},{"./xhr":20}],8:[function(e,t,r){"use strict";function o(e){for(var t,r=[],o=0;oe.length||128e.status){var t=e.headers.get("content-type");return i||t&&-1!==t.indexOf("application/json")?e.json():e.text()}return Promise.reject(new n.AppAuthError(e.status.toString(),e.statusText))})},t}(a);r.FetchRequestor=s;var p=function(e){function t(t){var r=e.call(this)||this;return r.promise=t,r}return o(t,e),t.prototype.xhr=function(){return this.promise},t}(a);r.TestRequestor=p},{"./errors":9}],21:[function(e,t,r){'use strict';function o(e){var t=e.length;if(0>16,l[d++]=255&t>>8,l[d++]=255&t;return 2===p&&(t=u[e.charCodeAt(r)]<<2|u[e.charCodeAt(r+1)]>>4,l[d++]=255&t),1===p&&(t=u[e.charCodeAt(r)]<<10|u[e.charCodeAt(r+1)]<<4|u[e.charCodeAt(r+2)]>>2,l[d++]=255&t>>8,l[d++]=255&t),l}function s(e){return d[63&e>>18]+d[63&e>>12]+d[63&e>>6]+d[63&e]}function p(e,t,r){for(var o,n=[],a=t;al?l:s+a));return 1===o?(t=e[r-1],n.push(d[t>>2]+d[63&t<<4]+"==")):2===o&&(t=(e[r-2]<<8)+e[r-1],n.push(d[t>>10]+d[63&t>>4]+d[63&t<<2]+"=")),n.join("")}r.byteLength=function(e){var t=o(e),r=t[0],n=t[1];return 3*(r+n)/4-n},r.toByteArray=a,r.fromByteArray=l;for(var d=[],u=[],c="undefined"==typeof Uint8Array?Array:Uint8Array,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",y=0,f=h.length;yarguments.length)&&s.call(arguments,1);return p[t]=!0,a(function(){p[t]&&(o?e.apply(null,o):e.call(null),r.clearImmediate(t))}),t},r.clearImmediate="function"==typeof o?o:function(e){delete p[e]}}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":22,timers:24}],25:[function(){(function(e){(function(e){var t=function checkIfIteratorIsSupported(){try{return!!Symbol.iterator}catch(e){return!1}}(),r=function(e){var r={next:function next(){var t=e.shift();return{done:void 0===t,value:t}}};return t&&(r[Symbol.iterator]=function(){return r}),r},o=function(e){return encodeURIComponent(e).replace(/%20/g,"+")},n=function(e){return decodeURIComponent((e+"").replace(/\+/g," "))};(function checkIfURLSearchParamsSupported(){try{var t=e.URLSearchParams;return"a=1"===new t("?a=1").toString()&&"function"==typeof t.prototype.set&&"function"==typeof t.prototype.entries}catch(t){return!1}})()||function polyfillURLSearchParams(){var n=function(e){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var t=_typeof(e);if("undefined"===t);else if("string"===t)""!==e&&this._fromString(e);else if(e instanceof n){var r=this;e.forEach(function(e,t){r.append(t,e)})}else if(!(null!==e&&"object"===t))throw new TypeError("Unsupported input's type for URLSearchParams");else if("[object Array]"===Object.prototype.toString.call(e)){for(var o,a=0;at[0]?1:0}),e._entries&&(e._entries={});for(var r=0;rt.end-t.pos||t.end>e.length)throw new RangeError("Malformed DER");var r=e[t.pos++],o=e[t.pos++];if(128<=o){if(o&=127,t.end-t.pos>24,255&l>>16,255&l>>8,255&l);1>24);)l<<=8,o--;4>o&&t.splice(a,4-o),o|=128}return t.splice(a-2,2,r,o),t}function y(e,t,r,o){Object.defineProperties(this,{_key:{value:e},type:{value:e.type,enumerable:!0},extractable:{value:void 0===r?e.extractable:r,enumerable:!0},algorithm:{value:void 0===t?e.algorithm:t,enumerable:!0},usages:{value:void 0===o?e.usages:o,enumerable:!0}})}function f(e){return"verify"===e||"encrypt"===e||"wrapKey"===e}function g(e){return"sign"===e||"decrypt"===e||"unwrapKey"===e}if("function"!=typeof Promise)throw"Promise support required";var _=e.crypto||e.msCrypto;if(_){var A=_.subtle||_.webkitSubtle;if(A){var T=e.Crypto||_.constructor||Object,v=e.SubtleCrypto||A.constructor||Object,S=e.CryptoKey||e.Key||Object,E=-1>3)),c,m,T);if(x&&"generateKey"===e&&"RSASSA-PKCS1-v1_5"===c.name&&(!c.modulusLength||2048<=c.modulusLength))return r=i(r),r.name="RSAES-PKCS1-v1_5",delete r.hash,A.generateKey(r,!0,["encrypt","decrypt"]).then(function(e){return Promise.all([A.exportKey("jwk",e.publicKey),A.exportKey("jwk",e.privateKey)])}).then(function(e){return e[0].alg=e[1].alg=s(c),e[0].key_ops=T.filter(f),e[1].key_ops=T.filter(g),Promise.all([A.importKey("jwk",e[0],c,!0,e[0].key_ops),A.importKey("jwk",e[1],c,m,e[1].key_ops)])}).then(function(e){return{publicKey:e[0],privateKey:e[1]}});if((x||R&&"SHA-1"===(c.hash||{}).name)&&"importKey"===e&&"jwk"===r&&"HMAC"===c.name&&"oct"===u.kty)return A.importKey("raw",n(o(u.k)),h,v[3],v[4]);if(x&&"importKey"===e&&("spki"===r||"pkcs8"===r))return A.importKey("jwk",d(u),h,v[3],v[4]);if(R&&"unwrapKey"===e)return A.decrypt(v[3],h,u).then(function(e){return A.importKey(r,e,v[4],v[5],v[6])});var S;try{S=t.apply(A,v)}catch(t){return Promise.reject(t)}return R&&(S=new Promise(function(e,t){S.onabort=S.onerror=function(r){t(r)},S.oncomplete=function(t){e(t.target.result)}})),S=S.then(function(e){return"HMAC"!==c.name||c.length||(c.length=8*e.algorithm.length),0==c.name.search("RSA")&&(!c.modulusLength&&(c.modulusLength=(e.publicKey||e).algorithm.modulusLength),!c.publicExponent&&(c.publicExponent=(e.publicKey||e).algorithm.publicExponent)),e=e.publicKey&&e.privateKey?{publicKey:new y(e.publicKey,c,m,T.filter(f)),privateKey:new y(e.privateKey,c,m,T.filter(g))}:new y(e,c,m,T),e}),S}}),["exportKey","wrapKey"].forEach(function(e){var r=A[e];A[e]=function(o,i,l){var d=[].slice.call(arguments);if("exportKey"===e?d[1]=i._key:"wrapKey"===e?(d[1]=i._key,d[2]=l._key):void 0,(x||R&&"SHA-1"===(i.algorithm.hash||{}).name)&&"exportKey"===e&&"jwk"===o&&"HMAC"===i.algorithm.name&&(d[0]="raw"),x&&"exportKey"===e&&("spki"===o||"pkcs8"===o)&&(d[0]="jwk"),R&&"wrapKey"===e)return A.exportKey(o,i).then(function(e){return"jwk"===o&&(e=n(unescape(encodeURIComponent(JSON.stringify(p(e)))))),A.encrypt(d[3],l,e)});var c;try{c=r.apply(A,d)}catch(t){return Promise.reject(t)}return R&&(c=new Promise(function(e,t){c.onabort=c.onerror=function(r){t(r)},c.oncomplete=function(t){e(t.target.result)}})),"exportKey"===e&&"jwk"===o&&(c=c.then(function(e){return(x||R&&"SHA-1"===(i.algorithm.hash||{}).name)&&"HMAC"===i.algorithm.name?{kty:"oct",alg:s(i.algorithm),key_ops:i.usages.slice(),ext:!0,k:t(a(e))}:(e=p(e),e.alg||(e.alg=s(i.algorithm)),e.key_ops||(e.key_ops="public"===i.type?i.usages.filter(f):"private"===i.type?i.usages.filter(g):i.usages.slice()),e)})),x&&"exportKey"===e&&("spki"===o||"pkcs8"===o)&&(c=c.then(function(e){return e=u(p(e)),e})),c}}),["encrypt","decrypt","sign","verify"].forEach(function(e){var t=A[e];A[e]=function(r,o,n,a){if(R&&(!n.byteLength||a&&!a.byteLength))throw new Error("Empy input is not allowed");var s=[].slice.call(arguments),p=i(r);if(R&&("sign"===e||"verify"===e)&&("RSASSA-PKCS1-v1_5"===r||"HMAC"===r)&&(s[0]={name:r}),R&&o.algorithm.hash&&(s[0].hash=s[0].hash||o.algorithm.hash),R&&"decrypt"===e&&"AES-GCM"===p.name){var l=r.tagLength>>3;s[2]=(n.buffer||n).slice(0,n.byteLength-l),r.tag=(n.buffer||n).slice(n.byteLength-l)}s[1]=o._key;var d;try{d=t.apply(A,s)}catch(t){return Promise.reject(t)}return R&&(d=new Promise(function(o,n){d.onabort=d.onerror=function(t){n(t)},d.oncomplete=function(n){var n=n.target.result;if("encrypt"===e&&n instanceof AesGcmEncryptResult){var a=n.ciphertext,i=n.tag;n=new Uint8Array(a.byteLength+i.byteLength),n.set(new Uint8Array(a),0),n.set(new Uint8Array(i),a.byteLength),n=n.buffer}o(n)}})),d}}),R){var P=A.digest;A.digest=function(e,t){if(!t.byteLength)throw new Error("Empy input is not allowed");var r;try{r=P.call(A,e,t)}catch(t){return Promise.reject(t)}return r=new Promise(function(e,t){r.onabort=r.onerror=function(r){t(r)},r.oncomplete=function(t){e(t.target.result)}}),r},e.crypto=Object.create(_,{getRandomValues:{value:function value(e){return _.getRandomValues(e)}},subtle:{value:A}}),e.CryptoKey=y}x&&(_.subtle=A,e.Crypto=T,e.SubtleCrypto=v,e.CryptoKey=y)}}}})},{}],27:[function(e,t,r){(function(e,o){"object"===_typeof(r)&&"undefined"!=typeof t?o(r):"function"==typeof define&&define.amd?define(["exports"],o):o(e.WHATWGFetch={})})(this,function(e){function t(e){return e&&DataView.prototype.isPrototypeOf(e)}function r(e){if("string"!=typeof e&&(e+=""),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||""===e)throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function o(e){return"string"!=typeof e&&(e+=""),e}function n(e){var t={next:function next(){var t=e.shift();return{done:void 0===t,value:t}}};return b.iterable&&(t[Symbol.iterator]=function(){return t}),t}function a(e){this.map={},e instanceof a?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function i(e){return e.bodyUsed?Promise.reject(new TypeError("Already read")):void(e.bodyUsed=!0)}function s(e){return new Promise(function(t,r){e.onload=function(){t(e.result)},e.onerror=function(){r(e.error)}})}function p(e){var t=new FileReader,r=s(t);return t.readAsArrayBuffer(e),r}function l(e){var t=new FileReader,r=s(t);return t.readAsText(e),r}function d(e){for(var t=new Uint8Array(e),r=Array(t.length),o=0;othis.status,this.statusText="statusText"in t?t.statusText:"",this.headers=new a(t.headers),this.url=t.url||"",this._initBody(e)}function m(t,r){return new Promise(function(o,n){function a(){s.abort()}var i=new y(t,r);if(i.signal&&i.signal.aborted)return n(new e.DOMException("Aborted","AbortError"));var s=new XMLHttpRequest;s.onload=function(){var e={status:s.status,statusText:s.statusText,headers:g(s.getAllResponseHeaders()||"")};e.url="responseURL"in s?s.responseURL:e.headers.get("X-Request-URL");var t="response"in s?s.response:s.responseText;setTimeout(function(){o(new _(t,e))},0)},s.onerror=function(){setTimeout(function(){n(new TypeError("Network request failed"))},0)},s.ontimeout=function(){setTimeout(function(){n(new TypeError("Network request failed"))},0)},s.onabort=function(){setTimeout(function(){n(new e.DOMException("Aborted","AbortError"))},0)},s.open(i.method,function(t){try{return""===t&&k.location.href?k.location.href:t}catch(r){return t}}(i.url),!0),"include"===i.credentials?s.withCredentials=!0:"omit"===i.credentials&&(s.withCredentials=!1),"responseType"in s&&(b.blob?s.responseType="blob":b.arrayBuffer&&i.headers.get("Content-Type")&&-1!==i.headers.get("Content-Type").indexOf("application/octet-stream")&&(s.responseType="arraybuffer")),i.headers.forEach(function(e,t){s.setRequestHeader(t,e)}),i.signal&&(i.signal.addEventListener("abort",a),s.onreadystatechange=function(){4===s.readyState&&i.signal.removeEventListener("abort",a)}),s.send("undefined"==typeof i._bodyInit?null:i._bodyInit)})}var k=function(e){return e}("undefined"==typeof self?this:self),b={searchParams:"URLSearchParams"in k,iterable:"Symbol"in k&&"iterator"in Symbol,blob:"FileReader"in k&&"Blob"in k&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in k,arrayBuffer:"ArrayBuffer"in k};if(b.arrayBuffer)var A=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],T=ArrayBuffer.isView||function(e){return e&&-1r.BUILT_IN_PARAMETERS.indexOf(n)&&(o[n]=t.extras[n]);var a=this.utils.stringify(o),i=e.authorizationEndpoint;return i+"?"+a},e.prototype.completeAuthorizationRequestIfPossible=function(){var e=this;return o.log("Checking to see if there is an authorization response to be delivered."),this.notifier||o.log("Notifier is not present on AuthorizationRequest handler.\n No delivery of result will be possible"),this.completeAuthorizationRequest().then(function(t){t||o.log("No result is available yet."),t&&e.notifier&&e.notifier.onAuthorizationComplete(t.request,t.response,t.error)})},e.prototype.setAuthorizationNotifier=function(e){return this.notifier=e,this},e}();r.AuthorizationRequestHandler=a},{"./logger":12}],6:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var o=function(){function e(e){this.code=e.code,this.state=e.state}return e.prototype.toJson=function(){return{code:this.code,state:this.state}},e}();r.AuthorizationResponse=o;var n=function(){function e(e){this.error=e.error,this.errorDescription=e.error_description,this.errorUri=e.error_uri,this.state=e.state}return e.prototype.toJson=function(){return{error:this.error,error_description:this.errorDescription,error_uri:this.errorUri,state:this.state}},e}();r.AuthorizationError=n},{}],7:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var o=e("./xhr"),n=function(){function e(e){this.authorizationEndpoint=e.authorization_endpoint,this.tokenEndpoint=e.token_endpoint,this.revocationEndpoint=e.revocation_endpoint,this.userInfoEndpoint=e.userinfo_endpoint,this.endSessionEndpoint=e.end_session_endpoint}return e.prototype.toJson=function(){return{authorization_endpoint:this.authorizationEndpoint,token_endpoint:this.tokenEndpoint,revocation_endpoint:this.revocationEndpoint,end_session_endpoint:this.endSessionEndpoint,userinfo_endpoint:this.userInfoEndpoint}},e.fetchFromIssuer=function(t,r){var n=r||new o.JQueryRequestor;return n.xhr({url:t+"/"+".well-known"+"/"+"openid-configuration",dataType:"json",method:"GET"}).then(function(t){return new e(t)})},e}();r.AuthorizationServiceConfiguration=n},{"./xhr":20}],8:[function(e,t,r){"use strict";function o(e){for(var t,r=[],o=0;oe.length||128e.status){var t=e.headers.get("content-type");return i||t&&-1!==t.indexOf("application/json")?e.json():e.text()}return Promise.reject(new n.AppAuthError(e.status.toString(),e.statusText))})},t}(a);r.FetchRequestor=s;var p=function(e){function t(t){var r=e.call(this)||this;return r.promise=t,r}return o(t,e),t.prototype.xhr=function(){return this.promise},t}(a);r.TestRequestor=p},{"./errors":9}],21:[function(e,t,r){'use strict';function o(e){var t=e.length;if(0>16,l[d++]=255&t>>8,l[d++]=255&t;return 2===p&&(t=u[e.charCodeAt(r)]<<2|u[e.charCodeAt(r+1)]>>4,l[d++]=255&t),1===p&&(t=u[e.charCodeAt(r)]<<10|u[e.charCodeAt(r+1)]<<4|u[e.charCodeAt(r+2)]>>2,l[d++]=255&t>>8,l[d++]=255&t),l}function s(e){return d[63&e>>18]+d[63&e>>12]+d[63&e>>6]+d[63&e]}function p(e,t,r){for(var o,n=[],a=t;al?l:s+a));return 1===o?(t=e[r-1],n.push(d[t>>2]+d[63&t<<4]+"==")):2===o&&(t=(e[r-2]<<8)+e[r-1],n.push(d[t>>10]+d[63&t>>4]+d[63&t<<2]+"=")),n.join("")}r.byteLength=function(e){var t=o(e),r=t[0],n=t[1];return 3*(r+n)/4-n},r.toByteArray=a,r.fromByteArray=l;for(var d=[],u=[],c="undefined"==typeof Uint8Array?Array:Uint8Array,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",y=0,f=h.length;yarguments.length)&&s.call(arguments,1);return p[t]=!0,a(function(){p[t]&&(o?e.apply(null,o):e.call(null),r.clearImmediate(t))}),t},r.clearImmediate="function"==typeof o?o:function(e){delete p[e]}}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":22,timers:24}],25:[function(){(function(e){(function(e){var t=function checkIfIteratorIsSupported(){try{return!!Symbol.iterator}catch(e){return!1}}(),r=function(e){var r={next:function next(){var t=e.shift();return{done:void 0===t,value:t}}};return t&&(r[Symbol.iterator]=function(){return r}),r},o=function(e){return encodeURIComponent(e).replace(/%20/g,"+")},n=function(e){return decodeURIComponent((e+"").replace(/\+/g," "))};(function checkIfURLSearchParamsSupported(){try{var t=e.URLSearchParams;return"a=1"===new t("?a=1").toString()&&"function"==typeof t.prototype.set&&"function"==typeof t.prototype.entries}catch(t){return!1}})()||function polyfillURLSearchParams(){var n=function(e){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var t=_typeof(e);if("undefined"===t);else if("string"===t)""!==e&&this._fromString(e);else if(e instanceof n){var r=this;e.forEach(function(e,t){r.append(t,e)})}else if(!(null!==e&&"object"===t))throw new TypeError("Unsupported input's type for URLSearchParams");else if("[object Array]"===Object.prototype.toString.call(e)){for(var o,a=0;at[0]?1:0}),e._entries&&(e._entries={});for(var r=0;rt.end-t.pos||t.end>e.length)throw new RangeError("Malformed DER");var r=e[t.pos++],o=e[t.pos++];if(128<=o){if(o&=127,t.end-t.pos>24,255&l>>16,255&l>>8,255&l);1>24);)l<<=8,o--;4>o&&t.splice(a,4-o),o|=128}return t.splice(a-2,2,r,o),t}function y(e,t,r,o){Object.defineProperties(this,{_key:{value:e},type:{value:e.type,enumerable:!0},extractable:{value:void 0===r?e.extractable:r,enumerable:!0},algorithm:{value:void 0===t?e.algorithm:t,enumerable:!0},usages:{value:void 0===o?e.usages:o,enumerable:!0}})}function f(e){return"verify"===e||"encrypt"===e||"wrapKey"===e}function g(e){return"sign"===e||"decrypt"===e||"unwrapKey"===e}if("function"!=typeof Promise)throw"Promise support required";var _=e.crypto||e.msCrypto;if(_){var A=_.subtle||_.webkitSubtle;if(A){var v=e.Crypto||_.constructor||Object,T=e.SubtleCrypto||A.constructor||Object,S=e.CryptoKey||e.Key||Object,E=-1>3)),c,m,v);if(x&&"generateKey"===e&&"RSASSA-PKCS1-v1_5"===c.name&&(!c.modulusLength||2048<=c.modulusLength))return r=i(r),r.name="RSAES-PKCS1-v1_5",delete r.hash,A.generateKey(r,!0,["encrypt","decrypt"]).then(function(e){return Promise.all([A.exportKey("jwk",e.publicKey),A.exportKey("jwk",e.privateKey)])}).then(function(e){return e[0].alg=e[1].alg=s(c),e[0].key_ops=v.filter(f),e[1].key_ops=v.filter(g),Promise.all([A.importKey("jwk",e[0],c,!0,e[0].key_ops),A.importKey("jwk",e[1],c,m,e[1].key_ops)])}).then(function(e){return{publicKey:e[0],privateKey:e[1]}});if((x||R&&"SHA-1"===(c.hash||{}).name)&&"importKey"===e&&"jwk"===r&&"HMAC"===c.name&&"oct"===u.kty)return A.importKey("raw",n(o(u.k)),h,T[3],T[4]);if(x&&"importKey"===e&&("spki"===r||"pkcs8"===r))return A.importKey("jwk",d(u),h,T[3],T[4]);if(R&&"unwrapKey"===e)return A.decrypt(T[3],h,u).then(function(e){return A.importKey(r,e,T[4],T[5],T[6])});var S;try{S=t.apply(A,T)}catch(t){return Promise.reject(t)}return R&&(S=new Promise(function(e,t){S.onabort=S.onerror=function(r){t(r)},S.oncomplete=function(t){e(t.target.result)}})),S=S.then(function(e){return"HMAC"!==c.name||c.length||(c.length=8*e.algorithm.length),0==c.name.search("RSA")&&(!c.modulusLength&&(c.modulusLength=(e.publicKey||e).algorithm.modulusLength),!c.publicExponent&&(c.publicExponent=(e.publicKey||e).algorithm.publicExponent)),e=e.publicKey&&e.privateKey?{publicKey:new y(e.publicKey,c,m,v.filter(f)),privateKey:new y(e.privateKey,c,m,v.filter(g))}:new y(e,c,m,v),e}),S}}),["exportKey","wrapKey"].forEach(function(e){var r=A[e];A[e]=function(o,i,l){var d=[].slice.call(arguments);if("exportKey"===e?d[1]=i._key:"wrapKey"===e?(d[1]=i._key,d[2]=l._key):void 0,(x||R&&"SHA-1"===(i.algorithm.hash||{}).name)&&"exportKey"===e&&"jwk"===o&&"HMAC"===i.algorithm.name&&(d[0]="raw"),x&&"exportKey"===e&&("spki"===o||"pkcs8"===o)&&(d[0]="jwk"),R&&"wrapKey"===e)return A.exportKey(o,i).then(function(e){return"jwk"===o&&(e=n(unescape(encodeURIComponent(JSON.stringify(p(e)))))),A.encrypt(d[3],l,e)});var c;try{c=r.apply(A,d)}catch(t){return Promise.reject(t)}return R&&(c=new Promise(function(e,t){c.onabort=c.onerror=function(r){t(r)},c.oncomplete=function(t){e(t.target.result)}})),"exportKey"===e&&"jwk"===o&&(c=c.then(function(e){return(x||R&&"SHA-1"===(i.algorithm.hash||{}).name)&&"HMAC"===i.algorithm.name?{kty:"oct",alg:s(i.algorithm),key_ops:i.usages.slice(),ext:!0,k:t(a(e))}:(e=p(e),e.alg||(e.alg=s(i.algorithm)),e.key_ops||(e.key_ops="public"===i.type?i.usages.filter(f):"private"===i.type?i.usages.filter(g):i.usages.slice()),e)})),x&&"exportKey"===e&&("spki"===o||"pkcs8"===o)&&(c=c.then(function(e){return e=u(p(e)),e})),c}}),["encrypt","decrypt","sign","verify"].forEach(function(e){var t=A[e];A[e]=function(r,o,n,a){if(R&&(!n.byteLength||a&&!a.byteLength))throw new Error("Empy input is not allowed");var s=[].slice.call(arguments),p=i(r);if(R&&("sign"===e||"verify"===e)&&("RSASSA-PKCS1-v1_5"===r||"HMAC"===r)&&(s[0]={name:r}),R&&o.algorithm.hash&&(s[0].hash=s[0].hash||o.algorithm.hash),R&&"decrypt"===e&&"AES-GCM"===p.name){var l=r.tagLength>>3;s[2]=(n.buffer||n).slice(0,n.byteLength-l),r.tag=(n.buffer||n).slice(n.byteLength-l)}s[1]=o._key;var d;try{d=t.apply(A,s)}catch(t){return Promise.reject(t)}return R&&(d=new Promise(function(o,n){d.onabort=d.onerror=function(t){n(t)},d.oncomplete=function(n){var n=n.target.result;if("encrypt"===e&&n instanceof AesGcmEncryptResult){var a=n.ciphertext,i=n.tag;n=new Uint8Array(a.byteLength+i.byteLength),n.set(new Uint8Array(a),0),n.set(new Uint8Array(i),a.byteLength),n=n.buffer}o(n)}})),d}}),R){var P=A.digest;A.digest=function(e,t){if(!t.byteLength)throw new Error("Empy input is not allowed");var r;try{r=P.call(A,e,t)}catch(t){return Promise.reject(t)}return r=new Promise(function(e,t){r.onabort=r.onerror=function(r){t(r)},r.oncomplete=function(t){e(t.target.result)}}),r},e.crypto=Object.create(_,{getRandomValues:{value:function value(e){return _.getRandomValues(e)}},subtle:{value:A}}),e.CryptoKey=y}x&&(_.subtle=A,e.Crypto=v,e.SubtleCrypto=T,e.CryptoKey=y)}}}})},{}],27:[function(e,t,r){(function(e,o){"object"===_typeof(r)&&"undefined"!=typeof t?o(r):"function"==typeof define&&define.amd?define(["exports"],o):o(e.WHATWGFetch={})})(this,function(e){function t(e){return e&&DataView.prototype.isPrototypeOf(e)}function r(e){if("string"!=typeof e&&(e+=""),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||""===e)throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function o(e){return"string"!=typeof e&&(e+=""),e}function n(e){var t={next:function next(){var t=e.shift();return{done:void 0===t,value:t}}};return b.iterable&&(t[Symbol.iterator]=function(){return t}),t}function a(e){this.map={},e instanceof a?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function i(e){return e.bodyUsed?Promise.reject(new TypeError("Already read")):void(e.bodyUsed=!0)}function s(e){return new Promise(function(t,r){e.onload=function(){t(e.result)},e.onerror=function(){r(e.error)}})}function p(e){var t=new FileReader,r=s(t);return t.readAsArrayBuffer(e),r}function l(e){var t=new FileReader,r=s(t);return t.readAsText(e),r}function d(e){for(var t=new Uint8Array(e),r=Array(t.length),o=0;othis.status,this.statusText="statusText"in t?t.statusText:"",this.headers=new a(t.headers),this.url=t.url||"",this._initBody(e)}function m(t,r){return new Promise(function(o,n){function a(){s.abort()}var i=new y(t,r);if(i.signal&&i.signal.aborted)return n(new e.DOMException("Aborted","AbortError"));var s=new XMLHttpRequest;s.onload=function(){var e={status:s.status,statusText:s.statusText,headers:g(s.getAllResponseHeaders()||"")};e.url="responseURL"in s?s.responseURL:e.headers.get("X-Request-URL");var t="response"in s?s.response:s.responseText;setTimeout(function(){o(new _(t,e))},0)},s.onerror=function(){setTimeout(function(){n(new TypeError("Network request failed"))},0)},s.ontimeout=function(){setTimeout(function(){n(new TypeError("Network request failed"))},0)},s.onabort=function(){setTimeout(function(){n(new e.DOMException("Aborted","AbortError"))},0)},s.open(i.method,function(t){try{return""===t&&k.location.href?k.location.href:t}catch(r){return t}}(i.url),!0),"include"===i.credentials?s.withCredentials=!0:"omit"===i.credentials&&(s.withCredentials=!1),"responseType"in s&&(b.blob?s.responseType="blob":b.arrayBuffer&&i.headers.get("Content-Type")&&-1!==i.headers.get("Content-Type").indexOf("application/octet-stream")&&(s.responseType="arraybuffer")),i.headers.forEach(function(e,t){s.setRequestHeader(t,e)}),i.signal&&(i.signal.addEventListener("abort",a),s.onreadystatechange=function(){4===s.readyState&&i.signal.removeEventListener("abort",a)}),s.send("undefined"==typeof i._bodyInit?null:i._bodyInit)})}var k=function(e){return e}("undefined"==typeof self?this:self),b={searchParams:"URLSearchParams"in k,iterable:"Symbol"in k&&"iterator"in Symbol,blob:"FileReader"in k&&"Blob"in k&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in k,arrayBuffer:"ArrayBuffer"in k};if(b.arrayBuffer)var A=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],v=ArrayBuffer.isView||function(e){return e&&-1
- Logout + Logout @@ -39,20 +39,30 @@ resourceServers: { "https://default.iam.example.com/am/oauth2/userinfo": "profile", - "https://default.iam.example.com/openidm": "openid" + "https://default.iam.example.com/openidm": "fr:idm:*" }, /* - interactionRequiredHandler: function () { + interactionRequiredHandler: function (authorization_request_url, error_reported) { // If you want to handle login at the IDP using some mechanism other than // the default (standard OAuth2 redirection to the authorizationEndpoint), // you can add that logic here. // Call AppAuthHelper.getTokens(); again when login is finished. }, */ - tokensAvailableHandler: function (claims) { + tokensAvailableHandler: function (claims, id_token, interactively_logged_in) { // This is a great place to startup the parts of your SPA that are for logged-in users. + // The "claims" parameter is the content of the id_token, which tells you useful details - // about the logged-in user. + // about the logged-in user. It will be undefined if you aren't using OIDC. + + // The "id_token" is the actual id_token value, which can be useful to have in its original form + // for various use-cases; OP-based session management may be one such case. + // See the companion library "oidcsessioncheck" for further details. + + // The "interactively_logged_in" parameter is a boolean; it lets your app know that tokens + // are available because the user just returned from the OP (rather than reading them from browser + // storage). This may be useful in some circumstances for user-experience concerns; for example, + // you should take care to avoid looping redirections between the OP and RP by checking this value. // Here is a sample "application" that just makes some requests to // resource servers and outputs the response on the page.