angular-oauth2-oidc
Version:
Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
32 lines • 149 kB
Source Map (JSON)
{
"version": 3,
"file": "angular-oauth2-oidc.umd.min.js",
"sources": [
"ng://angular-oauth2-oidc/node_modules/tslib/tslib.es6.js",
"ng://angular-oauth2-oidc/out/types.ts",
"ng://angular-oauth2-oidc/out/token-validation/validation-handler.ts",
"ng://angular-oauth2-oidc/out/url-helper.service.ts",
"ng://angular-oauth2-oidc/out/events.ts",
"ng://angular-oauth2-oidc/out/base64-helper.ts",
"ng://angular-oauth2-oidc/out/auth.config.ts",
"ng://angular-oauth2-oidc/out/encoder.ts",
"ng://angular-oauth2-oidc/out/oauth-service.ts",
"ng://angular-oauth2-oidc/out/oauth-module.config.ts",
"ng://angular-oauth2-oidc/out/interceptors/resource-server-error-handler.ts",
"ng://angular-oauth2-oidc/out/interceptors/default-oauth.interceptor.ts",
"ng://angular-oauth2-oidc/out/token-validation/null-validation-handler.ts",
"ng://angular-oauth2-oidc/out/factories.ts",
"ng://angular-oauth2-oidc/out/angular-oauth-oidic.module.ts",
"ng://angular-oauth2-oidc/out/token-validation/jwks-validation-handler.ts",
"ng://angular-oauth2-oidc/out/tokens.ts"
],
"sourcesContent": [
"/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\r\n t[p[i]] = s[p[i]];\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n",
"/**\r\n * Additional options that can be passt to tryLogin.\r\n */\r\nexport class LoginOptions {\r\n /**\r\n * Is called, after a token has been received and\r\n * successfully validated.\r\n *\r\n * Deprecated: Use property ``events`` on OAuthService instead.\r\n */\r\n onTokenReceived?: (receivedTokens: ReceivedTokens) => void;\r\n\r\n /**\r\n * Hook, to validate the received tokens.\r\n *\r\n * Deprecated: Use property ``tokenValidationHandler`` on OAuthService instead.\r\n */\r\n validationHandler?: (receivedTokens: ReceivedTokens) => Promise<any>;\r\n\r\n /**\r\n * Called when tryLogin detects that the auth server\r\n * included an error message into the hash fragment.\r\n *\r\n * Deprecated: Use property ``events`` on OAuthService instead.\r\n */\r\n onLoginError?: (params: object) => void;\r\n\r\n /**\r\n * A custom hash fragment to be used instead of the\r\n * actual one. This is used for silent refreshes, to\r\n * pass the iframes hash fragment to this method.\r\n */\r\n customHashFragment?: string;\r\n\r\n /**\r\n * Set this to true to disable the oauth2 state\r\n * check which is a best practice to avoid\r\n * security attacks.\r\n * As OIDC defines a nonce check that includes\r\n * this, this can be set to true when only doing\r\n * OIDC.\r\n */\r\n disableOAuth2StateCheck?: boolean;\r\n\r\n /**\r\n * Normally, you want to clear your hash fragment after\r\n * the lib read the token(s) so that they are not displayed\r\n * anymore in the url. If not, set this to true.\r\n */\r\n preventClearHashAfterLogin? = false;\r\n}\r\n\r\n/**\r\n * Defines the logging interface the OAuthService uses\r\n * internally. Is compatible with the `console` object,\r\n * but you can provide your own implementation as well\r\n * through dependency injection.\r\n */\r\nexport abstract class OAuthLogger {\r\n abstract debug(message?: any, ...optionalParams: any[]): void;\r\n abstract info(message?: any, ...optionalParams: any[]): void;\r\n abstract log(message?: any, ...optionalParams: any[]): void;\r\n abstract warn(message?: any, ...optionalParams: any[]): void;\r\n abstract error(message?: any, ...optionalParams: any[]): void;\r\n}\r\n\r\n/**\r\n * Defines a simple storage that can be used for\r\n * storing the tokens at client side.\r\n * Is compatible to localStorage and sessionStorage,\r\n * but you can also create your own implementations.\r\n */\r\nexport abstract class OAuthStorage {\r\n abstract getItem(key: string): string | null;\r\n abstract removeItem(key: string): void;\r\n abstract setItem(key: string, data: string): void;\r\n}\r\n\r\n/**\r\n * Represents the received tokens, the received state\r\n * and the parsed claims from the id-token.\r\n */\r\nexport class ReceivedTokens {\r\n idToken: string;\r\n accessToken: string;\r\n idClaims?: object;\r\n state?: string;\r\n}\r\n\r\n/**\r\n * Represents the parsed and validated id_token.\r\n */\r\nexport interface ParsedIdToken {\r\n idToken: string;\r\n idTokenClaims: object;\r\n idTokenHeader: object;\r\n idTokenClaimsJson: string;\r\n idTokenHeaderJson: string;\r\n idTokenExpiresAt: number;\r\n}\r\n\r\n/**\r\n * Represents the response from the token endpoint\r\n * http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint\r\n */\r\nexport interface TokenResponse {\r\n access_token: string;\r\n token_type: string;\r\n expires_in: number;\r\n refresh_token: string;\r\n scope: string;\r\n state?: string;\r\n}\r\n\r\n/**\r\n * Represents the response from the user info endpoint\r\n * http://openid.net/specs/openid-connect-core-1_0.html#UserInfo\r\n */\r\nexport interface UserInfo {\r\n sub: string;\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * Represents an OpenID Connect discovery document\r\n */\r\nexport interface OidcDiscoveryDoc {\r\n issuer: string;\r\n authorization_endpoint: string;\r\n token_endpoint: string;\r\n token_endpoint_auth_methods_supported: string[];\r\n token_endpoint_auth_signing_alg_values_supported: string[];\r\n userinfo_endpoint: string;\r\n check_session_iframe: string;\r\n end_session_endpoint: string;\r\n jwks_uri: string;\r\n registration_endpoint: string;\r\n scopes_supported: string[];\r\n response_types_supported: string[];\r\n acr_values_supported: string[];\r\n response_modes_supported: string[];\r\n grant_types_supported: string[];\r\n subject_types_supported: string[];\r\n userinfo_signing_alg_values_supported: string[];\r\n userinfo_encryption_alg_values_supported: string[];\r\n userinfo_encryption_enc_values_supported: string[];\r\n id_token_signing_alg_values_supported: string[];\r\n id_token_encryption_alg_values_supported: string[];\r\n id_token_encryption_enc_values_supported: string[];\r\n request_object_signing_alg_values_supported: string[];\r\n display_values_supported: string[];\r\n claim_types_supported: string[];\r\n claims_supported: string[];\r\n claims_parameter_supported: boolean;\r\n service_documentation: string;\r\n ui_locales_supported: string[];\r\n}\r\n",
"export interface ValidationParams {\r\n idToken: string;\r\n accessToken: string;\r\n idTokenHeader: object;\r\n idTokenClaims: object;\r\n jwks: object;\r\n loadKeys: () => Promise<object>;\r\n}\r\n\r\n/**\r\n * Interface for Handlers that are hooked in to\r\n * validate tokens.\r\n */\r\nexport abstract class ValidationHandler {\r\n /**\r\n * Validates the signature of an id_token.\r\n */\r\n public abstract validateSignature(\r\n validationParams: ValidationParams\r\n ): Promise<any>;\r\n\r\n /**\r\n * Validates the at_hash in an id_token against the received access_token.\r\n */\r\n public abstract validateAtHash(validationParams: ValidationParams): Promise<boolean>;\r\n}\r\n\r\n/**\r\n * This abstract implementation of ValidationHandler already implements\r\n * the method validateAtHash. However, to make use of it,\r\n * you have to override the method calcHash.\r\n */\r\nexport abstract class AbstractValidationHandler implements ValidationHandler {\r\n /**\r\n * Validates the signature of an id_token.\r\n */\r\n abstract validateSignature(validationParams: ValidationParams): Promise<any>;\r\n\r\n /**\r\n * Validates the at_hash in an id_token against the received access_token.\r\n */\r\n async validateAtHash(params: ValidationParams): Promise<boolean> {\r\n let hashAlg = this.inferHashAlgorithm(params.idTokenHeader);\r\n\r\n let tokenHash = await this.calcHash(params.accessToken, hashAlg); // sha256(accessToken, { asString: true });\r\n\r\n let leftMostHalf = tokenHash.substr(0, tokenHash.length / 2);\r\n\r\n let tokenHashBase64 = btoa(leftMostHalf);\r\n\r\n let atHash = tokenHashBase64\r\n .replace(/\\+/g, '-')\r\n .replace(/\\//g, '_')\r\n .replace(/=/g, '');\r\n let claimsAtHash = params.idTokenClaims['at_hash'].replace(/=/g, '');\r\n\r\n if (atHash !== claimsAtHash) {\r\n console.error('exptected at_hash: ' + atHash);\r\n console.error('actual at_hash: ' + claimsAtHash);\r\n }\r\n\r\n return atHash === claimsAtHash;\r\n }\r\n\r\n /**\r\n * Infers the name of the hash algorithm to use\r\n * from the alg field of an id_token.\r\n *\r\n * @param jwtHeader the id_token's parsed header\r\n */\r\n protected inferHashAlgorithm(jwtHeader: object): string {\r\n let alg: string = jwtHeader['alg'];\r\n \r\n if (!alg.match(/^.S[0-9]{3}$/)) {\r\n throw new Error('Algorithm not supported: ' + alg);\r\n }\r\n\r\n return 'sha-' + alg.substr(2);\r\n }\r\n\r\n /**\r\n * Calculates the hash for the passed value by using\r\n * the passed hash algorithm.\r\n *\r\n * @param valueToHash\r\n * @param algorithm\r\n */\r\n protected abstract calcHash(valueToHash: string, algorithm: string): Promise<string>;\r\n}\r\n",
"import { Injectable } from '@angular/core';\r\n\r\n@Injectable()\r\nexport class UrlHelperService {\r\n public getHashFragmentParams(customHashFragment?: string): object {\r\n let hash = customHashFragment || window.location.hash;\r\n\r\n hash = decodeURIComponent(hash);\r\n\r\n if (hash.indexOf('#') !== 0) {\r\n return {};\r\n }\r\n\r\n const questionMarkPosition = hash.indexOf('?');\r\n\r\n if (questionMarkPosition > -1) {\r\n hash = hash.substr(questionMarkPosition + 1);\r\n } else {\r\n hash = hash.substr(1);\r\n }\r\n\r\n return this.parseQueryString(hash);\r\n }\r\n\r\n public parseQueryString(queryString: string): object {\r\n const data = {};\r\n let\r\n pairs,\r\n pair,\r\n separatorIndex,\r\n escapedKey,\r\n escapedValue,\r\n key,\r\n value;\r\n\r\n if (queryString === null) {\r\n return data;\r\n }\r\n\r\n pairs = queryString.split('&');\r\n\r\n for (let i = 0; i < pairs.length; i++) {\r\n pair = pairs[i];\r\n separatorIndex = pair.indexOf('=');\r\n\r\n if (separatorIndex === -1) {\r\n escapedKey = pair;\r\n escapedValue = null;\r\n } else {\r\n escapedKey = pair.substr(0, separatorIndex);\r\n escapedValue = pair.substr(separatorIndex + 1);\r\n }\r\n\r\n key = decodeURIComponent(escapedKey);\r\n value = decodeURIComponent(escapedValue);\r\n\r\n if (key.substr(0, 1) === '/') { key = key.substr(1); }\r\n\r\n data[key] = value;\r\n }\r\n\r\n return data;\r\n }\r\n}\r\n",
"export type EventType =\r\n | 'discovery_document_loaded'\r\n | 'received_first_token'\r\n | 'jwks_load_error'\r\n | 'invalid_nonce_in_state'\r\n | 'discovery_document_load_error'\r\n | 'discovery_document_validation_error'\r\n | 'user_profile_loaded'\r\n | 'user_profile_load_error'\r\n | 'token_received'\r\n | 'token_error'\r\n | 'token_refreshed'\r\n | 'token_refresh_error'\r\n | 'silent_refresh_error'\r\n | 'silently_refreshed'\r\n | 'silent_refresh_timeout'\r\n | 'token_validation_error'\r\n | 'token_expires'\r\n | 'session_changed'\r\n | 'session_error'\r\n | 'session_terminated'\r\n | 'logout';\r\n\r\nexport abstract class OAuthEvent {\r\n constructor(readonly type: EventType) {}\r\n}\r\n\r\nexport class OAuthSuccessEvent extends OAuthEvent {\r\n constructor(type: EventType, readonly info: any = null) {\r\n super(type);\r\n }\r\n}\r\n\r\nexport class OAuthInfoEvent extends OAuthEvent {\r\n constructor(type: EventType, readonly info: any = null) {\r\n super(type);\r\n }\r\n}\r\n\r\nexport class OAuthErrorEvent extends OAuthEvent {\r\n constructor(\r\n type: EventType,\r\n readonly reason: object,\r\n readonly params: object = null\r\n ) {\r\n super(type);\r\n }\r\n}\r\n",
"// see: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22\r\nexport function b64DecodeUnicode(str) {\r\n const base64 = str.replace(/\\-/g, '+').replace(/\\_/g, '/');\r\n\r\n return decodeURIComponent(\r\n atob(base64)\r\n .split('')\r\n .map(function(c) {\r\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\r\n })\r\n .join('')\r\n );\r\n}\r\n",
"export class AuthConfig {\r\n /**\r\n * The client's id as registered with the auth server\r\n */\r\n public clientId? = '';\r\n\r\n /**\r\n * The client's redirectUri as registered with the auth server\r\n */\r\n public redirectUri? = '';\r\n\r\n /**\r\n * An optional second redirectUri where the auth server\r\n * redirects the user to after logging out.\r\n */\r\n public postLogoutRedirectUri? = '';\r\n\r\n /**\r\n * The auth server's endpoint that allows to log\r\n * the user in when using implicit flow.\r\n */\r\n public loginUrl? = '';\r\n\r\n /**\r\n * The requested scopes\r\n */\r\n public scope? = 'openid profile';\r\n\r\n public resource? = '';\r\n\r\n public rngUrl? = '';\r\n\r\n /**\r\n * Defines whether to use OpenId Connect during\r\n * implicit flow.\r\n */\r\n public oidc? = true;\r\n\r\n /**\r\n * Defines whether to request an access token during\r\n * implicit flow.\r\n */\r\n public requestAccessToken? = true;\r\n\r\n public options?: any = null;\r\n\r\n /**\r\n * The issuer's uri.\r\n */\r\n public issuer? = '';\r\n\r\n /**\r\n * The logout url.\r\n */\r\n public logoutUrl? = '';\r\n\r\n /**\r\n * Defines whether to clear the hash fragment after logging in.\r\n */\r\n public clearHashAfterLogin? = true;\r\n\r\n /**\r\n * Url of the token endpoint as defined by OpenId Connect and OAuth 2.\r\n */\r\n public tokenEndpoint?: string = null;\r\n\r\n /**\r\n * Url of the userinfo endpoint as defined by OpenId Connect.\r\n */\r\n public userinfoEndpoint?: string = null;\r\n\r\n public responseType? = '';\r\n\r\n /**\r\n * Defines whether additional debug information should\r\n * be shown at the console. Note that in certain browsers\r\n * the verbosity of the console needs to be explicitly set\r\n * to include Debug level messages.\r\n */\r\n public showDebugInformation? = false;\r\n\r\n /**\r\n * The redirect uri used when doing silent refresh.\r\n */\r\n public silentRefreshRedirectUri? = '';\r\n\r\n public silentRefreshMessagePrefix? = '';\r\n\r\n /**\r\n * Set this to true to display the iframe used for\r\n * silent refresh for debugging.\r\n */\r\n public silentRefreshShowIFrame? = false;\r\n\r\n /**\r\n * Timeout for silent refresh.\r\n * @internal\r\n * depreacted b/c of typo, see silentRefreshTimeout\r\n */\r\n public siletRefreshTimeout?: number = 1000 * 20;\r\n\r\n /**\r\n * Timeout for silent refresh.\r\n */\r\n public silentRefreshTimeout?: number = 1000 * 20;\r\n\r\n /**\r\n * Some auth servers don't allow using password flow\r\n * w/o a client secret while the standards do not\r\n * demand for it. In this case, you can set a password\r\n * here. As this password is exposed to the public\r\n * it does not bring additional security and is therefore\r\n * as good as using no password.\r\n */\r\n public dummyClientSecret?: string = null;\r\n\r\n /**\r\n * Defines whether https is required.\r\n * The default value is remoteOnly which only allows\r\n * http for localhost, while every other domains need\r\n * to be used with https.\r\n */\r\n public requireHttps?: boolean | 'remoteOnly' = 'remoteOnly';\r\n\r\n /**\r\n * Defines whether every url provided by the discovery\r\n * document has to start with the issuer's url.\r\n */\r\n public strictDiscoveryDocumentValidation? = true;\r\n\r\n /**\r\n * JSON Web Key Set (https://tools.ietf.org/html/rfc7517)\r\n * with keys used to validate received id_tokens.\r\n * This is taken out of the disovery document. Can be set manually too.\r\n */\r\n public jwks?: object = null;\r\n\r\n /**\r\n * Map with additional query parameter that are appended to\r\n * the request when initializing implicit flow.\r\n */\r\n public customQueryParams?: object = null;\r\n\r\n public silentRefreshIFrameName? = 'angular-oauth-oidc-silent-refresh-iframe';\r\n\r\n /**\r\n * Defines when the token_timeout event should be raised.\r\n * If you set this to the default value 0.75, the event\r\n * is triggered after 75% of the token's life time.\r\n */\r\n public timeoutFactor? = 0.75;\r\n\r\n /**\r\n * If true, the lib will try to check whether the user\r\n * is still logged in on a regular basis as described\r\n * in http://openid.net/specs/openid-connect-session-1_0.html#ChangeNotification\r\n */\r\n public sessionChecksEnabled? = false;\r\n\r\n /**\r\n * Interval in msec for checking the session\r\n * according to http://openid.net/specs/openid-connect-session-1_0.html#ChangeNotification\r\n */\r\n public sessionCheckIntervall? = 3 * 1000;\r\n\r\n /**\r\n * Url for the iframe used for session checks\r\n */\r\n public sessionCheckIFrameUrl?: string = null;\r\n\r\n /**\r\n * Name of the iframe to use for session checks\r\n */\r\n public sessionCheckIFrameName? = 'angular-oauth-oidc-check-session-iframe';\r\n\r\n /**\r\n * This property has been introduced to disable at_hash checks\r\n * and is indented for Identity Provider that does not deliver\r\n * an at_hash EVEN THOUGH its recommended by the OIDC specs.\r\n * Of course, when disabling these checks the we are bypassing\r\n * a security check which means we are more vulnerable.\r\n */\r\n public disableAtHashCheck? = false;\r\n\r\n /**\r\n * Defines wether to check the subject of a refreshed token after silent refresh.\r\n * Normally, it should be the same as before.\r\n */\r\n public skipSubjectCheck? = false;\r\n\r\n public useIdTokenHintForSilentRefresh? = false;\r\n\r\n /**\r\n * Defined whether to skip the validation of the issuer in the discovery document.\r\n * Normally, the discovey document's url starts with the url of the issuer.\r\n */\r\n public skipIssuerCheck? = false;\r\n\r\n /**\r\n * According to rfc6749 it is recommended (but not required) that the auth\r\n * server exposes the access_token's life time in seconds.\r\n * This is a fallback value for the case this value is not exposed.\r\n */\r\n public fallbackAccessTokenExpirationTimeInSec?: number;\r\n\r\n /**\r\n * final state sent to issuer is built as follows:\r\n * state = nonce + nonceStateSeparator + additional state\r\n * Default separator is ';' (encoded %3B).\r\n * In rare cases, this character might be forbidden or inconvenient to use by the issuer so it can be customized.\r\n */\r\n public nonceStateSeparator? = ';';\r\n\r\n /**\r\n * Set this to true to use HTTP BASIC auth for password flow\r\n */\r\n public useHttpBasicAuthForPasswordFlow? = false;\r\n\r\n constructor(json?: Partial<AuthConfig>) {\r\n if (json) {\r\n Object.assign(this, json);\r\n }\r\n }\r\n\r\n /**\r\n * This property allows you to override the method that is used to open the login url,\r\n * allowing a way for implementations to specify their own method of routing to new\r\n * urls.\r\n */\r\n public openUri?: ((uri: string) => void) = uri => {\r\n location.href = uri;\r\n }\r\n}\r\n",
"import { HttpParameterCodec } from '@angular/common/http';\r\n/**\r\n * This custom encoder allows charactes like +, % and / to be used in passwords\r\n */\r\nexport class WebHttpUrlEncodingCodec implements HttpParameterCodec {\r\n encodeKey(k: string): string {\r\n return encodeURIComponent(k);\r\n }\r\n\r\n encodeValue(v: string): string {\r\n return encodeURIComponent(v);\r\n }\r\n\r\n decodeKey(k: string): string {\r\n return decodeURIComponent(k);\r\n }\r\n\r\n decodeValue(v: string) {\r\n return decodeURIComponent(v);\r\n }\r\n}\r\n",
"import { Injectable, NgZone, Optional } from '@angular/core';\r\nimport { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { Observable, Subject, Subscription, of, race } from 'rxjs';\r\nimport { filter, take, delay, first, tap, map } from 'rxjs/operators';\r\n\r\nimport {\r\n ValidationHandler,\r\n ValidationParams\r\n} from './token-validation/validation-handler';\r\nimport { UrlHelperService } from './url-helper.service';\r\nimport {\r\n OAuthEvent,\r\n OAuthInfoEvent,\r\n OAuthErrorEvent,\r\n OAuthSuccessEvent\r\n} from './events';\r\nimport {\r\n OAuthLogger,\r\n OAuthStorage,\r\n LoginOptions,\r\n ParsedIdToken,\r\n OidcDiscoveryDoc,\r\n TokenResponse,\r\n UserInfo\r\n} from './types';\r\nimport { b64DecodeUnicode } from './base64-helper';\r\nimport { AuthConfig } from './auth.config';\r\nimport { WebHttpUrlEncodingCodec } from './encoder';\r\n\r\n/**\r\n * Service for logging in and logging out with\r\n * OIDC and OAuth2. Supports implicit flow and\r\n * password flow.\r\n */\r\n@Injectable()\r\nexport class OAuthService extends AuthConfig {\r\n // Extending AuthConfig ist just for LEGACY reasons\r\n // to not break existing code.\r\n\r\n /**\r\n * The ValidationHandler used to validate received\r\n * id_tokens.\r\n */\r\n public tokenValidationHandler: ValidationHandler;\r\n\r\n /**\r\n * @internal\r\n * Deprecated: use property events instead\r\n */\r\n public discoveryDocumentLoaded = false;\r\n\r\n /**\r\n * @internal\r\n * Deprecated: use property events instead\r\n */\r\n public discoveryDocumentLoaded$: Observable<object>;\r\n\r\n /**\r\n * Informs about events, like token_received or token_expires.\r\n * See the string enum EventType for a full list of event types.\r\n */\r\n public events: Observable<OAuthEvent>;\r\n\r\n /**\r\n * The received (passed around) state, when logging\r\n * in with implicit flow.\r\n */\r\n public state? = '';\r\n\r\n protected eventsSubject: Subject<OAuthEvent> = new Subject<OAuthEvent>();\r\n protected discoveryDocumentLoadedSubject: Subject<object> = new Subject<object>();\r\n protected silentRefreshPostMessageEventListener: EventListener;\r\n protected grantTypesSupported: Array<string> = [];\r\n protected _storage: OAuthStorage;\r\n protected accessTokenTimeoutSubscription: Subscription;\r\n protected idTokenTimeoutSubscription: Subscription;\r\n protected sessionCheckEventListener: EventListener;\r\n protected jwksUri: string;\r\n protected sessionCheckTimer: any;\r\n protected silentRefreshSubject: string;\r\n protected inImplicitFlow = false;\r\n\r\n constructor(\r\n protected ngZone: NgZone,\r\n protected http: HttpClient,\r\n @Optional() storage: OAuthStorage,\r\n @Optional() tokenValidationHandler: ValidationHandler,\r\n @Optional() protected config: AuthConfig,\r\n protected urlHelper: UrlHelperService,\r\n protected logger: OAuthLogger,\r\n ) {\r\n super();\r\n\r\n this.discoveryDocumentLoaded$ = this.discoveryDocumentLoadedSubject.asObservable();\r\n this.events = this.eventsSubject.asObservable();\r\n\r\n if (tokenValidationHandler) {\r\n this.tokenValidationHandler = tokenValidationHandler;\r\n }\r\n\r\n if (config) {\r\n this.configure(config);\r\n }\r\n\r\n try {\r\n if (storage) {\r\n this.setStorage(storage);\r\n } else if (typeof sessionStorage !== 'undefined') {\r\n this.setStorage(sessionStorage);\r\n }\r\n } catch (e) {\r\n\r\n console.error(\r\n 'No OAuthStorage provided and cannot access default (sessionStorage).'\r\n + 'Consider providing a custom OAuthStorage implementation in your module.',\r\n e\r\n );\r\n }\r\n\r\n this.setupRefreshTimer();\r\n }\r\n\r\n /**\r\n * Use this method to configure the service\r\n * @param config the configuration\r\n */\r\n public configure(config: AuthConfig) {\r\n // For the sake of downward compatibility with\r\n // original configuration API\r\n Object.assign(this, new AuthConfig(), config);\r\n\r\n this.config = Object.assign({} as AuthConfig, new AuthConfig(), config);\r\n\r\n if (this.sessionChecksEnabled) {\r\n this.setupSessionCheck();\r\n }\r\n\r\n this.configChanged();\r\n }\r\n\r\n protected configChanged(): void { }\r\n\r\n public restartSessionChecksIfStillLoggedIn(): void {\r\n if (this.hasValidIdToken()) {\r\n this.initSessionCheck();\r\n }\r\n }\r\n\r\n protected restartRefreshTimerIfStillLoggedIn(): void {\r\n this.setupExpirationTimers();\r\n }\r\n\r\n protected setupSessionCheck() {\r\n this.events.pipe(filter(e => e.type === 'token_received')).subscribe(e => {\r\n this.initSessionCheck();\r\n });\r\n }\r\n\r\n /**\r\n * Will setup up silent refreshing for when the token is\r\n * about to expire.\r\n * @param params Additional parameter to pass\r\n */\r\n public setupAutomaticSilentRefresh(params: object = {}) {\r\n this.events.pipe(filter(e => e.type === 'token_expires')).subscribe(e => {\r\n this.silentRefresh(params).catch(_ => {\r\n this.debug('Automatic silent refresh did not work');\r\n });\r\n });\r\n\r\n this.restartRefreshTimerIfStillLoggedIn();\r\n }\r\n\r\n\r\n /**\r\n * Convenience method that first calls `loadDiscoveryDocument(...)` and\r\n * directly chains using the `then(...)` part of the promise to call\r\n * the `tryLogin(...)` method.\r\n *\r\n * @param options LoginOptions to pass through to `tryLogin(...)`\r\n */\r\n public loadDiscoveryDocumentAndTryLogin(options: LoginOptions = null): Promise<boolean> {\r\n return this.loadDiscoveryDocument().then(doc => {\r\n return this.tryLogin(options);\r\n });\r\n }\r\n\r\n /**\r\n * Convenience method that first calls `loadDiscoveryDocumentAndTryLogin(...)`\r\n * and if then chains to `initImplicitFlow()`, but only if there is no valid\r\n * IdToken or no valid AccessToken.\r\n *\r\n * @param options LoginOptions to pass through to `tryLogin(...)`\r\n */\r\n public loadDiscoveryDocumentAndLogin(options: LoginOptions = null): Promise<boolean> {\r\n return this.loadDiscoveryDocumentAndTryLogin(options).then(_ => {\r\n if (!this.hasValidIdToken() || !this.hasValidAccessToken()) {\r\n this.initImplicitFlow();\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n });\r\n }\r\n\r\n protected debug(...args): void {\r\n if (this.showDebugInformation) {\r\n this.logger.debug.apply(console, args);\r\n }\r\n }\r\n\r\n protected validateUrlFromDiscoveryDocument(url: string): string[] {\r\n const errors: string[] = [];\r\n const httpsCheck = this.validateUrlForHttps(url);\r\n const issuerCheck = this.validateUrlAgainstIssuer(url);\r\n\r\n if (!httpsCheck) {\r\n errors.push(\r\n 'https for all urls required. Also for urls received by discovery.'\r\n );\r\n }\r\n\r\n if (!issuerCheck) {\r\n errors.push(\r\n 'Every url in discovery document has to start with the issuer url.' +\r\n 'Also see property strictDiscoveryDocumentValidation.'\r\n );\r\n }\r\n\r\n return errors;\r\n }\r\n\r\n protected validateUrlForHttps(url: string): boolean {\r\n if (!url) {\r\n return true;\r\n }\r\n\r\n const lcUrl = url.toLowerCase();\r\n\r\n if (this.requireHttps === false) {\r\n return true;\r\n }\r\n\r\n if (\r\n (lcUrl.match(/^http:\\/\\/localhost($|[:\\/])/) ||\r\n lcUrl.match(/^http:\\/\\/localhost($|[:\\/])/)) &&\r\n this.requireHttps === 'remoteOnly'\r\n ) {\r\n return true;\r\n }\r\n\r\n return lcUrl.startsWith('https://');\r\n }\r\n\r\n protected validateUrlAgainstIssuer(url: string) {\r\n if (!this.strictDiscoveryDocumentValidation) {\r\n return true;\r\n }\r\n if (!url) {\r\n return true;\r\n }\r\n return url.toLowerCase().startsWith(this.issuer.toLowerCase());\r\n }\r\n\r\n protected setupRefreshTimer(): void {\r\n if (typeof window === 'undefined') {\r\n this.debug('timer not supported on this plattform');\r\n return;\r\n }\r\n\r\n if (this.hasValidIdToken()) {\r\n this.clearAccessTokenTimer();\r\n this.clearIdTokenTimer();\r\n this.setupExpirationTimers();\r\n }\r\n\r\n this.events.pipe(filter(e => e.type === 'token_received')).subscribe(_ => {\r\n this.clearAccessTokenTimer();\r\n this.clearIdTokenTimer();\r\n this.setupExpirationTimers();\r\n });\r\n }\r\n\r\n protected setupExpirationTimers(): void {\r\n const idTokenExp = this.getIdTokenExpiration() || Number.MAX_VALUE;\r\n const accessTokenExp = this.getAccessTokenExpiration() || Number.MAX_VALUE;\r\n const useAccessTokenExp = accessTokenExp <= idTokenExp;\r\n\r\n if (this.hasValidAccessToken() && useAccessTokenExp) {\r\n this.setupAccessTokenTimer();\r\n }\r\n\r\n if (this.hasValidIdToken() && !useAccessTokenExp) {\r\n this.setupIdTokenTimer();\r\n }\r\n }\r\n\r\n protected setupAccessTokenTimer(): void {\r\n const expiration = this.getAccessTokenExpiration();\r\n const storedAt = this.getAccessTokenStoredAt();\r\n const timeout = this.calcTimeout(storedAt, expiration);\r\n\r\n this.ngZone.runOutsideAngular(() => {\r\n this.accessTokenTimeoutSubscription = of(\r\n new OAuthInfoEvent('token_expires', 'access_token')\r\n )\r\n .pipe(delay(timeout))\r\n .subscribe(e => {\r\n this.ngZone.run(() => {\r\n this.eventsSubject.next(e);\r\n });\r\n });\r\n });\r\n }\r\n\r\n protected setupIdTokenTimer(): void {\r\n const expiration = this.getIdTokenExpiration();\r\n const storedAt = this.getIdTokenStoredAt();\r\n const timeout = this.calcTimeout(storedAt, expiration);\r\n\r\n this.ngZone.runOutsideAngular(() => {\r\n this.idTokenTimeoutSubscription = of(\r\n new OAuthInfoEvent('token_expires', 'id_token')\r\n )\r\n .pipe(delay(timeout))\r\n .subscribe(e => {\r\n this.ngZone.run(() => {\r\n this.eventsSubject.next(e);\r\n });\r\n });\r\n });\r\n }\r\n\r\n protected clearAccessTokenTimer(): void {\r\n if (this.accessTokenTimeoutSubscription) {\r\n this.accessTokenTimeoutSubscription.unsubscribe();\r\n }\r\n }\r\n\r\n protected clearIdTokenTimer(): void {\r\n if (this.idTokenTimeoutSubscription) {\r\n this.idTokenTimeoutSubscription.unsubscribe();\r\n }\r\n }\r\n\r\n protected calcTimeout(storedAt: number, expiration: number): number {\r\n const delta = (expiration - storedAt) * this.timeoutFactor;\r\n return delta;\r\n }\r\n\r\n /**\r\n * DEPRECATED. Use a provider for OAuthStorage instead:\r\n *\r\n * { provide: OAuthStorage, useValue: localStorage }\r\n *\r\n * Sets a custom storage used to store the received\r\n * tokens on client side. By default, the browser's\r\n * sessionStorage is used.\r\n * @ignore\r\n *\r\n * @param storage\r\n */\r\n public setStorage(storage: OAuthStorage): void {\r\n this._storage = storage;\r\n this.configChanged();\r\n }\r\n\r\n /**\r\n * Loads the discovery document to configure most\r\n * properties of this service. The url of the discovery\r\n * document is infered from the issuer's url according\r\n * to the OpenId Connect spec. To use another url you\r\n * can pass it to to optional parameter fullUrl.\r\n *\r\n * @param fullUrl\r\n */\r\n public loadDiscoveryDocument(fullUrl: string = null): Promise<object> {\r\n return new Promise((resolve, reject) => {\r\n if (!fullUrl) {\r\n fullUrl = this.issuer || '';\r\n if (!fullUrl.endsWith('/')) {\r\n fullUrl += '/';\r\n }\r\n fullUrl += '.well-known/openid-configuration';\r\n }\r\n\r\n if (!this.validateUrlForHttps(fullUrl)) {\r\n reject('issuer must use https, or config value for property requireHttps must allow http');\r\n return;\r\n }\r\n\r\n this.http.get<OidcDiscoveryDoc>(fullUrl).subscribe(\r\n doc => {\r\n if (!this.validateDiscoveryDocument(doc)) {\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('discovery_document_validation_error', null)\r\n );\r\n reject('discovery_document_validation_error');\r\n return;\r\n }\r\n\r\n this.loginUrl = doc.authorization_endpoint;\r\n this.logoutUrl = doc.end_session_endpoint || this.logoutUrl;\r\n this.grantTypesSupported = doc.grant_types_supported;\r\n this.issuer = doc.issuer;\r\n this.tokenEndpoint = doc.token_endpoint;\r\n this.userinfoEndpoint = doc.userinfo_endpoint;\r\n this.jwksUri = doc.jwks_uri;\r\n this.sessionCheckIFrameUrl = doc.check_session_iframe || this.sessionCheckIFrameUrl;\r\n\r\n this.discoveryDocumentLoaded = true;\r\n this.discoveryDocumentLoadedSubject.next(doc);\r\n\r\n if (this.sessionChecksEnabled) {\r\n this.restartSessionChecksIfStillLoggedIn();\r\n }\r\n\r\n this.loadJwks()\r\n .then(jwks => {\r\n const result: object = {\r\n discoveryDocument: doc,\r\n jwks: jwks\r\n };\r\n\r\n const event = new OAuthSuccessEvent(\r\n 'discovery_document_loaded',\r\n result\r\n );\r\n this.eventsSubject.next(event);\r\n resolve(event);\r\n return;\r\n })\r\n .catch(err => {\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('discovery_document_load_error', err)\r\n );\r\n reject(err);\r\n return;\r\n });\r\n },\r\n err => {\r\n this.logger.error('error loading discovery document', err);\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('discovery_document_load_error', err)\r\n );\r\n reject(err);\r\n }\r\n );\r\n });\r\n }\r\n\r\n protected loadJwks(): Promise<object> {\r\n return new Promise<object>((resolve, reject) => {\r\n if (this.jwksUri) {\r\n this.http.get(this.jwksUri).subscribe(\r\n jwks => {\r\n this.jwks = jwks;\r\n this.eventsSubject.next(\r\n new OAuthSuccessEvent('discovery_document_loaded')\r\n );\r\n resolve(jwks);\r\n },\r\n err => {\r\n this.logger.error('error loading jwks', err);\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('jwks_load_error', err)\r\n );\r\n reject(err);\r\n }\r\n );\r\n } else {\r\n resolve(null);\r\n }\r\n });\r\n }\r\n\r\n protected validateDiscoveryDocument(doc: OidcDiscoveryDoc): boolean {\r\n let errors: string[];\r\n\r\n if (!this.skipIssuerCheck && doc.issuer !== this.issuer) {\r\n this.logger.error(\r\n 'invalid issuer in discovery document',\r\n 'expected: ' + this.issuer,\r\n 'current: ' + doc.issuer\r\n );\r\n return false;\r\n }\r\n\r\n errors = this.validateUrlFromDiscoveryDocument(doc.authorization_endpoint);\r\n if (errors.length > 0) {\r\n this.logger.error(\r\n 'error validating authorization_endpoint in discovery document',\r\n errors\r\n );\r\n return false;\r\n }\r\n\r\n errors = this.validateUrlFromDiscoveryDocument(doc.end_session_endpoint);\r\n if (errors.length > 0) {\r\n this.logger.error(\r\n 'error validating end_session_endpoint in discovery document',\r\n errors\r\n );\r\n return false;\r\n }\r\n\r\n errors = this.validateUrlFromDiscoveryDocument(doc.token_endpoint);\r\n if (errors.length > 0) {\r\n this.logger.error(\r\n 'error validating token_endpoint in discovery document',\r\n errors\r\n );\r\n }\r\n\r\n errors = this.validateUrlFromDiscoveryDocument(doc.userinfo_endpoint);\r\n if (errors.length > 0) {\r\n this.logger.error(\r\n 'error validating userinfo_endpoint in discovery document',\r\n errors\r\n );\r\n return false;\r\n }\r\n\r\n errors = this.validateUrlFromDiscoveryDocument(doc.jwks_uri);\r\n if (errors.length > 0) {\r\n this.logger.error('error validating jwks_uri in discovery document', errors);\r\n return false;\r\n }\r\n\r\n if (this.sessionChecksEnabled && !doc.check_session_iframe) {\r\n this.logger.warn(\r\n 'sessionChecksEnabled is activated but discovery document' +\r\n ' does not contain a check_session_iframe field'\r\n );\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Uses password flow to exchange userName and password for an\r\n * access_token. After receiving the access_token, this method\r\n * uses it to query the userinfo endpoint in order to get information\r\n * about the user in question.\r\n *\r\n * When using this, make sure that the property oidc is set to false.\r\n * Otherwise stricter validations take place that make this operation\r\n * fail.\r\n *\r\n * @param userName\r\n * @param password\r\n * @param headers Optional additional http-headers.\r\n */\r\n public fetchTokenUsingPasswordFlowAndLoadUserProfile(\r\n userName: string,\r\n password: string,\r\n headers: HttpHeaders = new HttpHeaders()\r\n ): Promise<object> {\r\n return this.fetchTokenUsingPasswordFlow(userName, password, headers).then(\r\n () => this.loadUserProfile()\r\n );\r\n }\r\n\r\n /**\r\n * Loads the user profile by accessing the user info endpoint defined by OpenId Connect.\r\n *\r\n * When using this with OAuth2 password flow, make sure that the property oidc is set to false.\r\n * Otherwise stricter v