1 | {
|
2 | "version": 3,
|
3 | "file": "angular-oauth2-oidc.umd.min.js",
|
4 | "sources": [
|
5 | "ng://angular-oauth2-oidc/node_modules/tslib/tslib.es6.js",
|
6 | "ng://angular-oauth2-oidc/out/types.ts",
|
7 | "ng://angular-oauth2-oidc/out/token-validation/validation-handler.ts",
|
8 | "ng://angular-oauth2-oidc/out/url-helper.service.ts",
|
9 | "ng://angular-oauth2-oidc/out/events.ts",
|
10 | "ng://angular-oauth2-oidc/out/base64-helper.ts",
|
11 | "ng://angular-oauth2-oidc/out/auth.config.ts",
|
12 | "ng://angular-oauth2-oidc/out/encoder.ts",
|
13 | "ng://angular-oauth2-oidc/out/oauth-service.ts",
|
14 | "ng://angular-oauth2-oidc/out/oauth-module.config.ts",
|
15 | "ng://angular-oauth2-oidc/out/interceptors/resource-server-error-handler.ts",
|
16 | "ng://angular-oauth2-oidc/out/interceptors/default-oauth.interceptor.ts",
|
17 | "ng://angular-oauth2-oidc/out/token-validation/null-validation-handler.ts",
|
18 | "ng://angular-oauth2-oidc/out/factories.ts",
|
19 | "ng://angular-oauth2-oidc/out/angular-oauth-oidic.module.ts",
|
20 | "ng://angular-oauth2-oidc/out/token-validation/jwks-validation-handler.ts",
|
21 | "ng://angular-oauth2-oidc/out/tokens.ts"
|
22 | ],
|
23 | "sourcesContent": [
|
24 | "/*! *****************************************************************************\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",
|
25 | "/**\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",
|
26 | "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",
|
27 | "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",
|
28 | "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",
|
29 | "// 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",
|
30 | "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",
|
31 | "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",
|
32 | "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 validations take place that make this operation fail.\r\n */\r\n public loadUserProfile(): Promise<object> {\r\n if (!this.hasValidAccessToken()) {\r\n throw new Error('Can not load User Profile without access_token');\r\n }\r\n if (!this.validateUrlForHttps(this.userinfoEndpoint)) {\r\n throw new Error(\r\n 'userinfoEndpoint must use http, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const headers = new HttpHeaders().set(\r\n 'Authorization',\r\n 'Bearer ' + this.getAccessToken()\r\n );\r\n\r\n this.http.get<UserInfo>(this.userinfoEndpoint, { headers }).subscribe(\r\n info => {\r\n this.debug('userinfo received', info);\r\n\r\n const existingClaims = this.getIdentityClaims() || {};\r\n\r\n if (!this.skipSubjectCheck) {\r\n if (\r\n this.oidc &&\r\n (!existingClaims['sub'] || info.sub !== existingClaims['sub'])\r\n ) {\r\n const err =\r\n 'if property oidc is true, the received user-id (sub) has to be the user-id ' +\r\n 'of the user that has logged in with oidc.\\n' +\r\n 'if you are not using oidc but just oauth2 password flow set oidc to false';\r\n\r\n reject(err);\r\n return;\r\n }\r\n }\r\n\r\n info = Object.assign({}, existingClaims, info);\r\n\r\n this._storage.setItem('id_token_claims_obj', JSON.stringify(info));\r\n this.eventsSubject.next(new OAuthSuccessEvent('user_profile_loaded'));\r\n resolve(info);\r\n },\r\n err => {\r\n this.logger.error('error loading user info', err);\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('user_profile_load_error', err)\r\n );\r\n reject(err);\r\n }\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Uses password flow to exchange userName and password for an access_token.\r\n * @param userName\r\n * @param password\r\n * @param headers Optional additional http-headers.\r\n */\r\n public fetchTokenUsingPasswordFlow(\r\n userName: string,\r\n password: string,\r\n headers: HttpHeaders = new HttpHeaders()\r\n ): Promise<object> {\r\n if (!this.validateUrlForHttps(this.tokenEndpoint)) {\r\n throw new Error(\r\n 'tokenEndpoint must use http, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n /**\r\n * A `HttpParameterCodec` that uses `encodeURIComponent` and `decodeURIComponent` to\r\n * serialize and parse URL parameter keys and values.\r\n *\r\n * @stable\r\n */\r\n let params = new HttpParams({ encoder: new WebHttpUrlEncodingCodec() })\r\n .set('grant_type', 'password')\r\n .set('scope', this.scope)\r\n .set('username', userName)\r\n .set('password', password);\r\n\r\n if (this.useHttpBasicAuthForPasswordFlow) {\r\n const header = btoa(`${this.clientId}:${this.dummyClientSecret}`);\r\n headers = headers.set(\r\n 'Authorization',\r\n 'Basic ' + header);\r\n }\r\n\r\n if (!this.useHttpBasicAuthForPasswordFlow) {\r\n params = params.set('client_id', this.clientId);\r\n }\r\n\r\n if (!this.useHttpBasicAuthForPasswordFlow && this.dummyClientSecret) {\r\n params = params.set('client_secret', this.dummyClientSecret);\r\n }\r\n\r\n if (this.customQueryParams) {\r\n for (const key of Object.getOwnPropertyNames(this.customQueryParams)) {\r\n params = params.set(key, this.customQueryParams[key]);\r\n }\r\n }\r\n\r\n headers = headers.set(\r\n 'Content-Type',\r\n 'application/x-www-form-urlencoded'\r\n );\r\n\r\n this.http\r\n .post<TokenResponse>(this.tokenEndpoint, params, { headers })\r\n .subscribe(\r\n tokenResponse => {\r\n this.debug('tokenResponse', tokenResponse);\r\n this.storeAccessTokenResponse(\r\n tokenResponse.access_token,\r\n tokenResponse.refresh_token,\r\n tokenResponse.expires_in,\r\n tokenResponse.scope\r\n );\r\n\r\n this.eventsSubject.next(new OAuthSuccessEvent('token_received'));\r\n resolve(tokenResponse);\r\n },\r\n err => {\r\n this.logger.error('Error performing password flow', err);\r\n this.eventsSubject.next(new OAuthErrorEvent('token_error', err));\r\n reject(err);\r\n }\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Refreshes the token using a refresh_token.\r\n * This does not work for implicit flow, b/c\r\n * there is no refresh_token in this flow.\r\n * A solution for this is provided by the\r\n * method silentRefresh.\r\n */\r\n public refreshToken(): Promise<object> {\r\n if (!this.validateUrlForHttps(this.tokenEndpoint)) {\r\n throw new Error(\r\n 'tokenEndpoint must use http, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n let params = new HttpParams()\r\n .set('grant_type', 'refresh_token')\r\n .set('client_id', this.clientId)\r\n .set('scope', this.scope)\r\n .set('refresh_token', this._storage.getItem('refresh_token'));\r\n\r\n if (this.dummyClientSecret) {\r\n params = params.set('client_secret', this.dummyClientSecret);\r\n }\r\n\r\n if (this.customQueryParams) {\r\n for (const key of Object.getOwnPropertyNames(this.customQueryParams)) {\r\n params = params.set(key, this.customQueryParams[key]);\r\n }\r\n }\r\n\r\n const headers = new HttpHeaders().set(\r\n 'Content-Type',\r\n 'application/x-www-form-urlencoded'\r\n );\r\n\r\n this.http\r\n .post<TokenResponse>(this.tokenEndpoint, params, { headers })\r\n .subscribe(\r\n tokenResponse => {\r\n this.debug('refresh tokenResponse', tokenResponse);\r\n this.storeAccessTokenResponse(\r\n tokenResponse.access_token,\r\n tokenResponse.refresh_token,\r\n tokenResponse.expires_in,\r\n tokenResponse.scope\r\n );\r\n\r\n this.eventsSubject.next(new OAuthSuccessEvent('token_received'));\r\n this.eventsSubject.next(new OAuthSuccessEvent('token_refreshed'));\r\n resolve(tokenResponse);\r\n },\r\n err => {\r\n this.logger.error('Error performing password flow', err);\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('token_refresh_error', err)\r\n );\r\n reject(err);\r\n }\r\n );\r\n });\r\n }\r\n\r\n protected removeSilentRefreshEventListener(): void {\r\n if (this.silentRefreshPostMessageEventListener) {\r\n window.removeEventListener(\r\n 'message',\r\n this.silentRefreshPostMessageEventListener\r\n );\r\n this.silentRefreshPostMessageEventListener = null;\r\n }\r\n }\r\n\r\n protected setupSilentRefreshEventListener(): void {\r\n this.removeSilentRefreshEventListener();\r\n\r\n this.silentRefreshPostMessageEventListener = (e: MessageEvent) => {\r\n let expectedPrefix = '#';\r\n\r\n if (this.silentRefreshMessagePrefix) {\r\n expectedPrefix += this.silentRefreshMessagePrefix;\r\n }\r\n\r\n if (!e || !e.data || typeof e.data !== 'string') {\r\n return;\r\n }\r\n\r\n const prefixedMessage: string = e.data;\r\n\r\n if (!prefixedMessage.startsWith(expectedPrefix)) {\r\n return;\r\n }\r\n\r\n const message = '#' + prefixedMessage.substr(expectedPrefix.length);\r\n\r\n this.tryLogin({\r\n customHashFragment: message,\r\n preventClearHashAfterLogin: true,\r\n onLoginError: err => {\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('silent_refresh_error', err)\r\n );\r\n },\r\n onTokenReceived: () => {\r\n this.eventsSubject.next(new OAuthSuccessEvent('silently_refreshed'));\r\n }\r\n }).catch(err => this.debug('tryLogin during silent refresh failed', err));\r\n };\r\n\r\n window.addEventListener(\r\n 'message',\r\n this.silentRefreshPostMessageEventListener\r\n );\r\n }\r\n\r\n /**\r\n * Performs a silent refresh for implicit flow.\r\n * Use this method to get new tokens when/before\r\n * the existing tokens expire.\r\n */\r\n public silentRefresh(params: object = {}, noPrompt = true): Promise<OAuthEvent> {\r\n const claims: object = this.getIdentityClaims() || {};\r\n\r\n if (this.useIdTokenHintForSilentRefresh && this.hasValidIdToken()) {\r\n params['id_token_hint'] = this.getIdToken();\r\n }\r\n\r\n if (!this.validateUrlForHttps(this.loginUrl)) {\r\n throw new Error(\r\n 'tokenEndpoint must use https, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n if (typeof document === 'undefined') {\r\n throw new Error('silent refresh is not supported on this platform');\r\n }\r\n\r\n const existingIframe = document.getElementById(\r\n this.silentRefreshIFrameName\r\n );\r\n\r\n if (existingIframe) {\r\n document.body.removeChild(existingIframe);\r\n }\r\n\r\n this.silentRefreshSubject = claims['sub'];\r\n\r\n const iframe = document.createElement('iframe');\r\n iframe.id = this.silentRefreshIFrameName;\r\n\r\n this.setupSilentRefreshEventListener();\r\n\r\n const redirectUri = this.silentRefreshRedirectUri || this.redirectUri;\r\n this.createLoginUrl(null, null, redirectUri, noPrompt, params).then(url => {\r\n iframe.setAttribute('src', url);\r\n\r\n if (!this.silentRefreshShowIFrame) {\r\n iframe.style['display'] = 'none';\r\n }\r\n document.body.appendChild(iframe);\r\n });\r\n\r\n const errors = this.events.pipe(\r\n filter(e => e instanceof OAuthErrorEvent),\r\n first()\r\n );\r\n const success = this.events.pipe(\r\n filter(e => e.type === 'silently_refreshed'),\r\n first()\r\n );\r\n const timeout = of(\r\n new OAuthErrorEvent('silent_refresh_timeout', null)\r\n ).pipe(delay(this.silentRefreshTimeout));\r\n\r\n return race([errors, success, timeout])\r\n .pipe(\r\n tap(e => {\r\n if (e.type === 'silent_refresh_timeout') {\r\n this.eventsSubject.next(e);\r\n }\r\n }),\r\n map(e => {\r\n if (e instanceof OAuthErrorEvent) {\r\n throw e;\r\n }\r\n return e;\r\n })\r\n )\r\n .toPromise();\r\n }\r\n\r\n protected canPerformSessionCheck(): boolean {\r\n if (!this.sessionChecksEnabled) {\r\n return false;\r\n }\r\n if (!this.sessionCheckIFrameUrl) {\r\n console.warn(\r\n 'sessionChecksEnabled is activated but there is no sessionCheckIFrameUrl'\r\n );\r\n return false;\r\n }\r\n const sessionState = this.getSessionState();\r\n if (!sessionState) {\r\n console.warn(\r\n 'sessionChecksEnabled is activated but there is no session_state'\r\n );\r\n return false;\r\n }\r\n if (typeof document === 'undefined') {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n protected setupSessionCheckEventListener(): void {\r\n this.removeSessionCheckEventListener();\r\n\r\n this.sessionCheckEventListener = (e: MessageEvent) => {\r\n const origin = e.origin.toLowerCase();\r\n const issuer = this.issuer.toLowerCase();\r\n\r\n this.debug('sessionCheckEventListener');\r\n\r\n if (!issuer.startsWith(origin)) {\r\n this.debug(\r\n 'sessionCheckEventListener',\r\n 'wrong origin',\r\n origin,\r\n 'expected',\r\n issuer\r\n );\r\n }\r\n\r\n // only run in Angular zone if it is 'changed' or 'error'\r\n switch (e.data) {\r\n case 'unchanged':\r\n this.handleSessionUnchanged();\r\n break;\r\n case 'changed':\r\n this.ngZone.run(() => {\r\n this.handleSessionChange() \r\n });\r\n break;\r\n case 'error':\r\n this.ngZone.run(() => { \r\n this.handleSessionError()\r\n });\r\n break;\r\n }\r\n\r\n this.debug('got info from session check inframe', e);\r\n };\r\n\r\n // prevent Angular from refreshing the view on every message (runs in intervals)\r\n this.ngZone.runOutsideAngular(() => {\r\n window.addEventListener('message', this.sessionCheckEventListener);\r\n });\r\n }\r\n\r\n protected handleSessionUnchanged(): void {\r\n this.debug('session check', 'session unchanged');\r\n }\r\n\r\n protected handleSessionChange(): void {\r\n /* events: session_changed, relogin, stopTimer, logged_out*/\r\n this.eventsSubject.next(new OAuthInfoEvent('session_changed'));\r\n this.stopSessionCheckTimer();\r\n if (this.silentRefreshRedirectUri) {\r\n this.silentRefresh().catch(_ =>\r\n this.debug('silent refresh failed after session changed')\r\n );\r\n this.waitForSilentRefreshAfterSessionChange();\r\n } else {\r\n this.eventsSubject.next(new OAuthInfoEvent('session_terminated'));\r\n this.logOut(true);\r\n }\r\n }\r\n\r\n protected waitForSilentRefreshAfterSessionChange() {\r\n this.events\r\n .pipe(\r\n filter(\r\n (e: OAuthEvent) =>\r\n e.type === 'silently_refreshed' ||\r\n e.type === 'silent_refresh_timeout' ||\r\n e.type === 'silent_refresh_error'\r\n ),\r\n first()\r\n )\r\n .subscribe(e => {\r\n if (e.type !== 'silently_refreshed') {\r\n this.debug('silent refresh did not work after session changed');\r\n this.eventsSubject.next(new OAuthInfoEvent('session_terminated'));\r\n this.logOut(true);\r\n }\r\n });\r\n }\r\n\r\n protected handleSessionError(): void {\r\n this.stopSessionCheckTimer();\r\n this.eventsSubject.next(new OAuthInfoEvent('session_error'));\r\n }\r\n\r\n protected removeSessionCheckEventListener(): void {\r\n if (this.sessionCheckEventListener) {\r\n window.removeEventListener('message', this.sessionCheckEventListener);\r\n this.sessionCheckEventListener = null;\r\n }\r\n }\r\n\r\n protected initSessionCheck(): void {\r\n if (!this.canPerformSessionCheck()) {\r\n return;\r\n }\r\n\r\n const existingIframe = document.getElementById(this.sessionCheckIFrameName);\r\n if (existingIframe) {\r\n document.body.removeChild(existingIframe);\r\n }\r\n\r\n const iframe = document.createElement('iframe');\r\n iframe.id = this.sessionCheckIFrameName;\r\n\r\n this.setupSessionCheckEventListener();\r\n\r\n const url = this.sessionCheckIFrameUrl;\r\n iframe.setAttribute('src', url);\r\n iframe.style.display = 'none';\r\n document.body.appendChild(iframe);\r\n\r\n this.startSessionCheckTimer();\r\n }\r\n\r\n protected startSessionCheckTimer(): void {\r\n this.stopSessionCheckTimer();\r\n this.ngZone.runOutsideAngular(() => {\r\n this.sessionCheckTimer = setInterval(\r\n this.checkSession.bind(this),\r\n this.sessionCheckIntervall\r\n );\r\n });\r\n }\r\n\r\n protected stopSessionCheckTimer(): void {\r\n if (this.sessionCheckTimer) {\r\n clearInterval(this.sessionCheckTimer);\r\n this.sessionCheckTimer = null;\r\n }\r\n }\r\n\r\n protected checkSession(): void {\r\n const iframe: any = document.getElementById(this.sessionCheckIFrameName);\r\n\r\n if (!iframe) {\r\n this.logger.warn(\r\n 'checkSession did not find iframe',\r\n this.sessionCheckIFrameName\r\n );\r\n }\r\n\r\n const sessionState = this.getSessionState();\r\n\r\n if (!sessionState) {\r\n this.stopSessionCheckTimer();\r\n }\r\n\r\n const message = this.clientId + ' ' + sessionState;\r\n iframe.contentWindow.postMessage(message, this.issuer);\r\n }\r\n\r\n protected createLoginUrl(\r\n state = '',\r\n loginHint = '',\r\n customRedirectUri = '',\r\n noPrompt = false,\r\n params: object = {}\r\n ) {\r\n const that = this;\r\n\r\n let redirectUri: string;\r\n\r\n if (customRedirectUri) {\r\n redirectUri = customRedirectUri;\r\n } else {\r\n redirectUri = this.redirectUri;\r\n }\r\n\r\n return this.createAndSaveNonce().then((nonce: any) => {\r\n if (state) {\r\n state = nonce + this.config.nonceStateSeparator + state;\r\n } else {\r\n state = nonce;\r\n }\r\n\r\n if (!this.requestAccessToken && !this.oidc) {\r\n throw new Error(\r\n 'Either requestAccessToken or oidc or both must be true'\r\n );\r\n }\r\n\r\n if (this.config.responseType) {\r\n this.responseType = this.config.responseType;\r\n } else {\r\n if (this.oidc && this.requestAccessToken) {\r\n this.responseType = 'id_token token';\r\n } else if (this.oidc && !this.requestAccessToken) {\r\n this.responseType = 'id_token';\r\n } else {\r\n this.responseType = 'token';\r\n }\r\n }\r\n\r\n const seperationChar = that.loginUrl.indexOf('?') > -1 ? '&' : '?';\r\n\r\n let scope = that.scope;\r\n\r\n if (this.oidc && !scope.match(/(^|\\s)openid($|\\s)/)) {\r\n scope = 'openid ' + scope;\r\n }\r\n\r\n let url =\r\n that.loginUrl +\r\n seperationChar +\r\n 'response_type=' +\r\n encodeURIComponent(that.responseType) +\r\n '&client_id=' +\r\n encodeURIComponent(that.clientId) +\r\n '&state=' +\r\n encodeURIComponent(state) +\r\n '&redirect_uri=' +\r\n encodeURIComponent(redirectUri) +\r\n '&scope=' +\r\n encodeURIComponent(scope);\r\n\r\n if (loginHint) {\r\n url += '&login_hint=' + encodeURIComponent(loginHint);\r\n }\r\n\r\n if (that.resource) {\r\n url += '&resource=' + encodeURIComponent(that.resource);\r\n }\r\n\r\n if (that.oidc) {\r\n url += '&nonce=' + encodeURIComponent(nonce);\r\n }\r\n\r\n if (noPrompt) {\r\n url += '&prompt=none';\r\n }\r\n\r\n for (const key of Object.keys(params)) {\r\n url +=\r\n '&' + encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);\r\n }\r\n\r\n if (this.customQueryParams) {\r\n for (const key of Object.getOwnPropertyNames(this.customQueryParams)) {\r\n url +=\r\n '&' + key + '=' + encodeURIComponent(this.customQueryParams[key]);\r\n }\r\n }\r\n\r\n return url;\r\n });\r\n }\r\n\r\n initImplicitFlowInternal(\r\n additionalState = '',\r\n params: string | object = ''\r\n ): void {\r\n if (this.inImplicitFlow) {\r\n return;\r\n }\r\n\r\n this.inImplicitFlow = true;\r\n\r\n if (!this.validateUrlForHttps(this.loginUrl)) {\r\n throw new Error(\r\n 'loginUrl must use http, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n let addParams: object = {};\r\n let loginHint: string = null;\r\n\r\n if (typeof params === 'string') {\r\n loginHint = params;\r\n } else if (typeof params === 'object') {\r\n addParams = params;\r\n }\r\n\r\n this.createLoginUrl(additionalState, loginHint, null, false, addParams)\r\n .then(function (url) {\r\n location.href = url;\r\n })\r\n .catch(error => {\r\n console.error('Error in initImplicitFlow', error);\r\n this.inImplicitFlow = false;\r\n });\r\n }\r\n\r\n /**\r\n * Starts the implicit flow and redirects to user to\r\n * the auth servers' login url.\r\n *\r\n * @param additionalState Optional state that is passed around.\r\n * You'll find this state in the property `state` after `tryLogin` logged in the user.\r\n * @param params Hash with additional parameter. If it is a string, it is used for the\r\n * parameter loginHint (for the sake of compatibility with former versions)\r\n */\r\n public initImplicitFlow(\r\n additionalState = '',\r\n params: string | object = ''\r\n ): void {\r\n if (this.loginUrl !== '') {\r\n this.initImplicitFlowInternal(additionalState, params);\r\n } else {\r\n this.events\r\n .pipe(filter(e => e.type === 'discovery_document_loaded'))\r\n .subscribe(_ => this.initImplicitFlowInternal(additionalState, params));\r\n }\r\n }\r\n\r\n protected callOnTokenReceivedIfExists(options: LoginOptions): void {\r\n const that = this;\r\n if (options.onTokenReceived) {\r\n const tokenParams = {\r\n idClaims: that.getIdentityClaims(),\r\n idToken: that.getIdToken(),\r\n accessToken: that.getAccessToken(),\r\n state: that.state\r\n };\r\n options.onTokenReceived(tokenParams);\r\n }\r\n }\r\n\r\n protected storeAccessTokenResponse(\r\n accessToken: string,\r\n refreshToken: string,\r\n expiresIn: number,\r\n grantedScopes: String\r\n ): void {\r\n this._storage.setItem('access_token', accessToken);\r\n if (grantedScopes) {\r\n this._storage.setItem('granted_scopes', JSON.stringify(grantedScopes.split('+')));\r\n }\r\n this._storage.setItem('access_token_stored_at', '' + Date.now());\r\n if (expiresIn) {\r\n const expiresInMilliSeconds = expiresIn * 1000;\r\n const now = new Date();\r\n const expiresAt = now.getTime() + expiresInMilliSeconds;\r\n this._storage.setItem('expires_at', '' + expiresAt);\r\n }\r\n\r\n if (refreshToken) {\r\n this._storage.setItem('refresh_token', refreshToken);\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether there are tokens in the hash fragment\r\n * as a result of the implicit flow. These tokens are\r\n * parsed, validated and used to sign the user in to the\r\n * current client.\r\n *\r\n * @param options Optional options.\r\n */\r\n public tryLogin(options: LoginOptions = null): Promise<boolean> {\r\n options = options || {};\r\n\r\n let parts: object;\r\n\r\n if (options.customHashFragment) {\r\n parts = this.urlHelper.getHashFragmentParams(options.customHashFragment);\r\n } else {\r\n parts = this.urlHelper.getHashFragmentParams();\r\n }\r\n\r\n this.debug('parsed url', parts);\r\n\r\n const state = parts['state'];\r\n let nonceInState = state;\r\n\r\n if (state) {\r\n const idx = state.indexOf(this.config.nonceStateSeparator);\r\n\r\n if (idx > -1) {\r\n nonceInState = state.substr(0, idx);\r\n this.state = state.substr(idx + this.config.nonceStateSeparator.length);\r\n }\r\n }\r\n\r\n if (parts['error']) {\r\n this.debug('error trying to login');\r\n this.handleLoginError(options, parts);\r\n const err = new OAuthErrorEvent('token_error', {}, parts);\r\n this.eventsSubject.next(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n const accessToken = parts['access_token'];\r\n const idToken = parts['id_token'];\r\n const sessionState = parts['session_state'];\r\n const grantedScopes = parts['scope'];\r\n\r\n if (!this.requestAccessToken && !this.oidc) {\r\n return Promise.reject(\r\n 'Either requestAccessToken or oidc (or both) must be true.'\r\n );\r\n }\r\n\r\n if (this.requestAccessToken && !accessToken) {\r\n return Promise.resolve(false);\r\n }\r\n if (this.requestAccessToken && !options.disableOAuth2StateCheck && !state) {\r\n return Promise.resolve(false);\r\n }\r\n if (this.oidc && !idToken) {\r\n return Promise.resolve(false);\r\n }\r\n\r\n if (this.sessionChecksEnabled && !sessionState) {\r\n this.logger.warn(\r\n 'session checks (Session Status Change Notification) ' +\r\n 'were activated in the configuration but the id_token ' +\r\n 'does not contain a session_state claim'\r\n );\r\n }\r\n\r\n if (this.requestAccessToken && !options.disableOAuth2StateCheck) {\r\n const success = this.validateNonceForAccessToken(\r\n accessToken,\r\n nonceInState\r\n );\r\n if (!success) {\r\n const event = new OAuthErrorEvent('invalid_nonce_in_state', null);\r\n this.eventsSubject.next(event);\r\n return Promise.reject(event);\r\n }\r\n }\r\n\r\n if (this.requestAccessToken) {\r\n this.storeAccessTokenResponse(\r\n accessToken,\r\n null,\r\n parts['expires_in'] || this.fallbackAccessTokenExpirationTimeInSec,\r\n grantedScopes\r\n );\r\n }\r\n\r\n if (!this.oidc) {\r\n this.eventsSubject.next(new OAuthSuccessEvent('token_received'));\r\n if (this.clearHashAfterLogin && !options.preventClearHashAfterLogin) {\r\n location.hash = '';\r\n }\r\n\r\n this.callOnTokenReceivedIfExists(options);\r\n return Promise.resolve(true);\r\n\r\n }\r\n\r\n return this.processIdToken(idToken, accessToken)\r\n .then(result => {\r\n if (options.validationHandler) {\r\n return options\r\n .validationHandler({\r\n accessToken: accessToken,\r\n idClaims: result.idTokenClaims,\r\n idToken: result.idToken,\r\n state: state\r\n })\r\n .then(_ => result);\r\n }\r\n return result;\r\n })\r\n .then(result => {\r\n this.storeIdToken(result);\r\n this.storeSessionState(sessionState);\r\n if (this.clearHashAfterLogin) {\r\n location.hash = '';\r\n }\r\n this.eventsSubject.next(new OAuthSuccessEvent('token_received'));\r\n this.callOnTokenReceivedIfExists(options);\r\n this.inImplicitFlow = false;\r\n return true;\r\n })\r\n .catch(reason => {\r\n this.eventsSubject.next(\r\n new OAuthErrorEvent('token_validation_error', reason)\r\n );\r\n this.logger.error('Error validating tokens');\r\n this.logger.error(reason);\r\n return Promise.reject(reason);\r\n });\r\n }\r\n\r\n protected validateNonceForAccessToken(\r\n accessToken: string,\r\n nonceInState: string\r\n ): boolean {\r\n const savedNonce = this._storage.getItem('nonce');\r\n if (savedNonce !== nonceInState) {\r\n const err = 'Validating access_token failed, wrong state/nonce.';\r\n console.error(err, savedNonce, nonceInState);\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n protected storeIdToken(idToken: ParsedIdToken) {\r\n this._storage.setItem('id_token', idToken.idToken);\r\n this._storage.setItem('id_token_claims_obj', idToken.idTokenClaimsJson);\r\n this._storage.setItem('id_token_expires_at', '' + idToken.idTokenExpiresAt);\r\n this._storage.setItem('id_token_stored_at', '' + Date.now());\r\n }\r\n\r\n protected storeSessionState(sessionState: string): void {\r\n this._storage.setItem('session_state', sessionState);\r\n }\r\n\r\n protected getSessionState(): string {\r\n return this._storage.getItem('session_state');\r\n }\r\n\r\n protected handleLoginError(options: LoginOptions, parts: object): void {\r\n if (options.onLoginError) {\r\n options.onLoginError(parts);\r\n }\r\n if (this.clearHashAfterLogin) {\r\n location.hash = '';\r\n }\r\n }\r\n\r\n /**\r\n * @ignore\r\n */\r\n public processIdToken(\r\n idToken: string,\r\n accessToken: string\r\n ): Promise<ParsedIdToken> {\r\n const tokenParts = idToken.split('.');\r\n const headerBase64 = this.padBase64(tokenParts[0]);\r\n const headerJson = b64DecodeUnicode(headerBase64);\r\n const header = JSON.parse(headerJson);\r\n const claimsBase64 = this.padBase64(tokenParts[1]);\r\n const claimsJson = b64DecodeUnicode(claimsBase64);\r\n const claims = JSON.parse(claimsJson);\r\n const savedNonce = this._storage.getItem('nonce');\r\n\r\n if (Array.isArray(claims.aud)) {\r\n if (claims.aud.every(v => v !== this.clientId)) {\r\n const err = 'Wrong audience: ' + claims.aud.join(',');\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n } else {\r\n if (claims.aud !== this.clientId) {\r\n const err = 'Wrong audience: ' + claims.aud;\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n }\r\n\r\n if (!claims.sub) {\r\n const err = 'No sub claim in id_token';\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n /* For now, we only check whether the sub against\r\n * silentRefreshSubject when sessionChecksEnabled is on\r\n * We will reconsider in a later version to do this\r\n * in every other case too.\r\n */\r\n if (\r\n this.sessionChecksEnabled &&\r\n this.silentRefreshSubject &&\r\n this.silentRefreshSubject !== claims['sub']\r\n ) {\r\n const err =\r\n 'After refreshing, we got an id_token for another user (sub). ' +\r\n `Expected sub: ${this.silentRefreshSubject}, received sub: ${\r\n claims['sub']\r\n }`;\r\n\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n if (!claims.iat) {\r\n const err = 'No iat claim in id_token';\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n if (claims.iss !== this.issuer) {\r\n const err = 'Wrong issuer: ' + claims.iss;\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n if (claims.nonce !== savedNonce) {\r\n const err = 'Wrong nonce: ' + claims.nonce;\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n if (\r\n !this.disableAtHashCheck &&\r\n this.requestAccessToken &&\r\n !claims['at_hash']\r\n ) {\r\n const err = 'An at_hash is needed!';\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n const now = Date.now();\r\n const issuedAtMSec = claims.iat * 1000;\r\n const expiresAtMSec = claims.exp * 1000;\r\n const tenMinutesInMsec = 1000 * 60 * 10;\r\n\r\n if (\r\n issuedAtMSec - tenMinutesInMsec >= now ||\r\n expiresAtMSec + tenMinutesInMsec <= now\r\n ) {\r\n const err = 'Token has expired';\r\n console.error(err);\r\n console.error({\r\n now: now,\r\n issuedAtMSec: issuedAtMSec,\r\n expiresAtMSec: expiresAtMSec\r\n });\r\n return Promise.reject(err);\r\n }\r\n\r\n const validationParams: ValidationParams = {\r\n accessToken: accessToken,\r\n idToken: idToken,\r\n jwks: this.jwks,\r\n idTokenClaims: claims,\r\n idTokenHeader: header,\r\n loadKeys: () => this.loadJwks()\r\n };\r\n\r\n\r\n return this.checkAtHash(validationParams)\r\n .then(atHashValid => {\r\n if (\r\n !this.disableAtHashCheck &&\r\n this.requestAccessToken &&\r\n !atHashValid\r\n ) {\r\n const err = 'Wrong at_hash';\r\n this.logger.warn(err);\r\n return Promise.reject(err);\r\n }\r\n\r\n return this.checkSignature(validationParams).then(_ => {\r\n const result: ParsedIdToken = {\r\n idToken: idToken,\r\n idTokenClaims: claims,\r\n idTokenClaimsJson: claimsJson,\r\n idTokenHeader: header,\r\n idTokenHeaderJson: headerJson,\r\n idTokenExpiresAt: expiresAtMSec\r\n };\r\n return result;\r\n });\r\n\r\n });\r\n }\r\n\r\n /**\r\n * Returns the received claims about the user.\r\n */\r\n public getIdentityClaims(): object {\r\n const claims = this._storage.getItem('id_token_claims_obj');\r\n if (!claims) {\r\n return null;\r\n }\r\n return JSON.parse(claims);\r\n }\r\n\r\n /**\r\n * Returns the granted scopes from the server.\r\n */\r\n public getGrantedScopes(): object {\r\n const scopes = this._storage.getItem('granted_scopes');\r\n if (!scopes) {\r\n return null;\r\n }\r\n return JSON.parse(scopes);\r\n }\r\n\r\n /**\r\n * Returns the current id_token.\r\n */\r\n public getIdToken(): string {\r\n return this._storage\r\n ? this._storage.getItem('id_token')\r\n : null;\r\n }\r\n\r\n protected padBase64(base64data): string {\r\n while (base64data.length % 4 !== 0) {\r\n base64data += '=';\r\n }\r\n return base64data;\r\n }\r\n\r\n /**\r\n * Returns the current access_token.\r\n */\r\n public getAccessToken(): string {\r\n return this._storage.getItem('access_token');\r\n }\r\n\r\n public getRefreshToken(): string {\r\n return this._storage.getItem('refresh_token');\r\n }\r\n\r\n /**\r\n * Returns the expiration date of the access_token\r\n * as milliseconds since 1970.\r\n */\r\n public getAccessTokenExpiration(): number {\r\n if (!this._storage.getItem('expires_at')) {\r\n return null;\r\n }\r\n return parseInt(this._storage.getItem('expires_at'), 10);\r\n }\r\n\r\n protected getAccessTokenStoredAt(): number {\r\n return parseInt(this._storage.getItem('access_token_stored_at'), 10);\r\n }\r\n\r\n protected getIdTokenStoredAt(): number {\r\n return parseInt(this._storage.getItem('id_token_stored_at'), 10);\r\n }\r\n\r\n /**\r\n * Returns the expiration date of the id_token\r\n * as milliseconds since 1970.\r\n */\r\n public getIdTokenExpiration(): number {\r\n if (!this._storage.getItem('id_token_expires_at')) {\r\n return null;\r\n }\r\n\r\n return parseInt(this._storage.getItem('id_token_expires_at'), 10);\r\n }\r\n\r\n /**\r\n * Checkes, whether there is a valid access_token.\r\n */\r\n public hasValidAccessToken(): boolean {\r\n if (this.getAccessToken()) {\r\n const expiresAt = this._storage.getItem('expires_at');\r\n const now = new Date();\r\n if (expiresAt && parseInt(expiresAt, 10) < now.getTime()) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether there is a valid id_token.\r\n */\r\n public hasValidIdToken(): boolean {\r\n if (this.getIdToken()) {\r\n const expiresAt = this._storage.getItem('id_token_expires_at');\r\n const now = new Date();\r\n if (expiresAt && parseInt(expiresAt, 10) < now.getTime()) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns the auth-header that can be used\r\n * to transmit the access_token to a service\r\n */\r\n public authorizationHeader(): string {\r\n return 'Bearer ' + this.getAccessToken();\r\n }\r\n\r\n /**\r\n * Removes all tokens and logs the user out.\r\n * If a logout url is configured, the user is\r\n * redirected to it.\r\n * @param noRedirectToLogoutUrl\r\n */\r\n public logOut(noRedirectToLogoutUrl = false): void {\r\n const id_token = this.getIdToken();\r\n this._storage.removeItem('access_token');\r\n this._storage.removeItem('id_token');\r\n this._storage.removeItem('refresh_token');\r\n this._storage.removeItem('nonce');\r\n this._storage.removeItem('expires_at');\r\n this._storage.removeItem('id_token_claims_obj');\r\n this._storage.removeItem('id_token_expires_at');\r\n this._storage.removeItem('id_token_stored_at');\r\n this._storage.removeItem('access_token_stored_at');\r\n this._storage.removeItem('granted_scopes');\r\n this._storage.removeItem('session_state');\r\n\r\n this.silentRefreshSubject = null;\r\n\r\n this.eventsSubject.next(new OAuthInfoEvent('logout'));\r\n\r\n if (!this.logoutUrl) {\r\n return;\r\n }\r\n if (noRedirectToLogoutUrl) {\r\n return;\r\n }\r\n\r\n if (!id_token && !this.postLogoutRedirectUri) {\r\n return;\r\n }\r\n\r\n let logoutUrl: string;\r\n\r\n if (!this.validateUrlForHttps(this.logoutUrl)) {\r\n throw new Error(\r\n 'logoutUrl must use http, or config value for property requireHttps must allow http'\r\n );\r\n }\r\n\r\n // For backward compatibility\r\n if (this.logoutUrl.indexOf('{{') > -1) {\r\n logoutUrl = this.logoutUrl\r\n .replace(/\\{\\{id_token\\}\\}/, id_token)\r\n .replace(/\\{\\{client_id\\}\\}/, this.clientId);\r\n } else {\r\n\r\n let params = new HttpParams();\r\n\r\n if (id_token) {\r\n params = params.set('id_token_hint', id_token);\r\n }\r\n\r\n const postLogoutUrl = this.postLogoutRedirectUri || this.redirectUri;\r\n if (postLogoutUrl) {\r\n params = params.set('post_logout_redirect_uri', postLogoutUrl);\r\n }\r\n\r\n logoutUrl =\r\n this.logoutUrl +\r\n (this.logoutUrl.indexOf('?') > -1 ? '&' : '?') +\r\n params.toString()\r\n }\r\n location.href = logoutUrl;\r\n }\r\n\r\n /**\r\n * @ignore\r\n */\r\n public createAndSaveNonce(): Promise<string> {\r\n const that = this;\r\n return this.createNonce().then(function (nonce: any) {\r\n that._storage.setItem('nonce', nonce);\r\n return nonce;\r\n });\r\n }\r\n\r\n protected createNonce(): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n if (this.rngUrl) {\r\n throw new Error(\r\n 'createNonce with rng-web-api has not been implemented so far'\r\n );\r\n } else {\r\n let text = '';\r\n const possible =\r\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r\n\r\n for (let i = 0; i < 40; i++) {\r\n text += possible.charAt(Math.floor(Math.random() * possible.length));\r\n }\r\n\r\n resolve(text);\r\n }\r\n });\r\n }\r\n\r\n protected async checkAtHash(params: ValidationParams): Promise<boolean> {\r\n if (!this.tokenValidationHandler) {\r\n this.logger.warn(\r\n 'No tokenValidationHandler configured. Cannot check at_hash.'\r\n );\r\n return true;\r\n }\r\n return this.tokenValidationHandler.validateAtHash(params);\r\n }\r\n\r\n protected checkSignature(params: ValidationParams): Promise<any> {\r\n if (!this.tokenValidationHandler) {\r\n this.logger.warn(\r\n 'No tokenValidationHandler configured. Cannot check signature.'\r\n );\r\n return Promise.resolve(null);\r\n }\r\n return this.tokenValidationHandler.validateSignature(params);\r\n }\r\n}\r\n",
|
33 | "export abstract class OAuthModuleConfig {\r\n resourceServer: OAuthResourceServerConfig;\r\n}\r\n\r\nexport abstract class OAuthResourceServerConfig {\r\n /**\r\n * Urls for which calls should be intercepted.\r\n * If there is an ResourceServerErrorHandler registered, it is used for them.\r\n * If sendAccessToken is set to true, the access_token is send to them too.\r\n */\r\n allowedUrls?: Array<string>;\r\n sendAccessToken: boolean;\r\n}\r\n",
|
34 | "import { HttpResponse } from '@angular/common/http';\r\nimport { Observable, throwError } from 'rxjs';\r\n\r\nexport abstract class OAuthResourceServerErrorHandler {\r\n abstract handleError(err: HttpResponse<any>): Observable<any>;\r\n}\r\n\r\nexport class OAuthNoopResourceServerErrorHandler\r\n implements OAuthResourceServerErrorHandler {\r\n handleError(err: HttpResponse<any>): Observable<any> {\r\n return throwError(err);\r\n }\r\n}\r\n",
|
35 | "import { Injectable, Inject, Optional } from '@angular/core';\r\nimport { OAuthService } from '../oauth-service';\r\nimport { OAuthStorage } from '../types';\r\nimport {\r\n HttpEvent,\r\n HttpHandler,\r\n HttpInterceptor,\r\n HttpRequest,\r\n HttpResponse,\r\n HttpErrorResponse\r\n} from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { OAuthResourceServerErrorHandler } from './resource-server-error-handler';\r\nimport { OAuthModuleConfig } from '../oauth-module.config';\r\n\r\n@Injectable()\r\nexport class DefaultOAuthInterceptor implements HttpInterceptor {\r\n constructor(\r\n private authStorage: OAuthStorage,\r\n private errorHandler: OAuthResourceServerErrorHandler,\r\n @Optional() private moduleConfig: OAuthModuleConfig\r\n ) { }\r\n\r\n private checkUrl(url: string): boolean {\r\n const found = this.moduleConfig.resourceServer.allowedUrls.find(u => url.startsWith(u));\r\n return !!found;\r\n }\r\n\r\n public intercept(\r\n req: HttpRequest<any>,\r\n next: HttpHandler\r\n ): Observable<HttpEvent<any>> {\r\n const url = req.url.toLowerCase();\r\n\r\n if (!this.moduleConfig) {\r\n return next.handle(req);\r\n }\r\n if (!this.moduleConfig.resourceServer) {\r\n return next.handle(req);\r\n }\r\n if (this.moduleConfig.resourceServer.allowedUrls && !this.checkUrl(url)) {\r\n return next.handle(req);\r\n }\r\n\r\n const sendAccessToken = this.moduleConfig.resourceServer.sendAccessToken;\r\n\r\n if (sendAccessToken && this.authStorage.getItem('access_token')) {\r\n const token = this.authStorage.getItem('access_token');\r\n const header = 'Bearer ' + token;\r\n\r\n const headers = req.headers.set('Authorization', header);\r\n\r\n req = req.clone({ headers });\r\n }\r\n\r\n return next\r\n .handle(req)\r\n .pipe(catchError(err => this.errorHandler.handleError(err)));\r\n }\r\n}\r\n",
|
36 | "import { ValidationHandler, ValidationParams } from './validation-handler';\r\n\r\n/**\r\n * A validation handler that isn't validating nothing.\r\n * Can be used to skip validation (at your own risk).\r\n */\r\nexport class NullValidationHandler implements ValidationHandler {\r\n validateSignature(validationParams: ValidationParams): Promise<any> {\r\n return Promise.resolve(null);\r\n }\r\n validateAtHash(validationParams: ValidationParams): Promise<boolean> {\r\n return Promise.resolve(true);\r\n }\r\n}\r\n",
|
37 | "export function createDefaultLogger() {\r\n return console;\r\n}\r\n\r\nexport function createDefaultStorage() {\r\n return typeof sessionStorage !== 'undefined' ? sessionStorage : null;\r\n}",
|
38 | "import { OAuthStorage, OAuthLogger } from './types';\r\nimport { NgModule, ModuleWithProviders } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';\r\n\r\nimport { OAuthService } from './oauth-service';\r\nimport { UrlHelperService } from './url-helper.service';\r\n\r\nimport { OAuthModuleConfig } from './oauth-module.config';\r\nimport {\r\n OAuthResourceServerErrorHandler,\r\n OAuthNoopResourceServerErrorHandler\r\n} from './interceptors/resource-server-error-handler';\r\nimport { DefaultOAuthInterceptor } from './interceptors/default-oauth.interceptor';\r\nimport { ValidationHandler } from './token-validation/validation-handler';\r\nimport { NullValidationHandler } from './token-validation/null-validation-handler';\r\nimport { createDefaultLogger, createDefaultStorage } from './factories';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [],\r\n exports: []\r\n})\r\nexport class OAuthModule {\r\n static forRoot(\r\n config: OAuthModuleConfig = null,\r\n validationHandlerClass = NullValidationHandler\r\n ): ModuleWithProviders {\r\n return {\r\n ngModule: OAuthModule,\r\n providers: [\r\n OAuthService,\r\n UrlHelperService,\r\n { provide: OAuthLogger, useFactory: createDefaultLogger },\r\n { provide: OAuthStorage, useFactory: createDefaultStorage },\r\n { provide: ValidationHandler, useClass: validationHandlerClass},\r\n {\r\n provide: OAuthResourceServerErrorHandler,\r\n useClass: OAuthNoopResourceServerErrorHandler\r\n },\r\n { provide: OAuthModuleConfig, useValue: config },\r\n {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: DefaultOAuthInterceptor,\r\n multi: true\r\n }\r\n ]\r\n };\r\n }\r\n}\r\n",
|
39 | "import {\r\n AbstractValidationHandler,\r\n ValidationParams\r\n} from './validation-handler';\r\n\r\n// declare var require: any;\r\n// let rs = require('jsrsasign');\r\n\r\nimport * as rs from 'jsrsasign';\r\n\r\n/**\r\n * Validates the signature of an id_token against one\r\n * of the keys of an JSON Web Key Set (jwks).\r\n *\r\n * This jwks can be provided by the discovery document.\r\n */\r\nexport class JwksValidationHandler extends AbstractValidationHandler {\r\n /**\r\n * Allowed algorithms\r\n */\r\n allowedAlgorithms: string[] = [\r\n 'HS256',\r\n 'HS384',\r\n 'HS512',\r\n 'RS256',\r\n 'RS384',\r\n 'RS512',\r\n 'ES256',\r\n 'ES384',\r\n 'PS256',\r\n 'PS384',\r\n 'PS512'\r\n ];\r\n\r\n /**\r\n * Time period in seconds the timestamp in the signature can\r\n * differ from the current time.\r\n */\r\n gracePeriodInSec = 600;\r\n\r\n validateSignature(params: ValidationParams, retry = false): Promise<any> {\r\n if (!params.idToken) throw new Error('Parameter idToken expected!');\r\n if (!params.idTokenHeader)\r\n throw new Error('Parameter idTokenHandler expected.');\r\n if (!params.jwks) throw new Error('Parameter jwks expected!');\r\n\r\n if (\r\n !params.jwks['keys'] ||\r\n !Array.isArray(params.jwks['keys']) ||\r\n params.jwks['keys'].length === 0\r\n ) {\r\n throw new Error('Array keys in jwks missing!');\r\n }\r\n\r\n // console.debug('validateSignature: retry', retry);\r\n\r\n let kid: string = params.idTokenHeader['kid'];\r\n let keys: object[] = params.jwks['keys'];\r\n let key: object;\r\n\r\n let alg = params.idTokenHeader['alg'];\r\n\r\n if (kid) {\r\n key = keys.find(k => k['kid'] === kid /* && k['use'] === 'sig' */);\r\n } else {\r\n let kty = this.alg2kty(alg);\r\n let matchingKeys = keys.filter(\r\n k => k['kty'] === kty && k['use'] === 'sig'\r\n );\r\n\r\n /*\r\n if (matchingKeys.length == 0) {\r\n let error = 'No matching key found.';\r\n console.error(error);\r\n return Promise.reject(error);\r\n }*/\r\n if (matchingKeys.length > 1) {\r\n let error =\r\n 'More than one matching key found. Please specify a kid in the id_token header.';\r\n console.error(error);\r\n return Promise.reject(error);\r\n } else if (matchingKeys.length === 1) {\r\n key = matchingKeys[0];\r\n }\r\n }\r\n\r\n if (!key && !retry && params.loadKeys) {\r\n return params\r\n .loadKeys()\r\n .then(loadedKeys => (params.jwks = loadedKeys))\r\n .then(_ => this.validateSignature(params, true));\r\n }\r\n\r\n if (!key && retry && !kid) {\r\n let error = 'No matching key found.';\r\n console.error(error);\r\n return Promise.reject(error);\r\n }\r\n\r\n if (!key && retry && kid) {\r\n let error =\r\n 'expected key not found in property jwks. ' +\r\n 'This property is most likely loaded with the ' +\r\n 'discovery document. ' +\r\n 'Expected key id (kid): ' +\r\n kid;\r\n\r\n console.error(error);\r\n return Promise.reject(error);\r\n }\r\n\r\n let keyObj = rs.KEYUTIL.getKey(key);\r\n let validationOptions = {\r\n alg: this.allowedAlgorithms,\r\n gracePeriod: this.gracePeriodInSec\r\n };\r\n let isValid = rs.KJUR.jws.JWS.verifyJWT(\r\n params.idToken,\r\n keyObj,\r\n validationOptions\r\n );\r\n\r\n if (isValid) {\r\n return Promise.resolve();\r\n } else {\r\n return Promise.reject('Signature not valid');\r\n }\r\n }\r\n\r\n private alg2kty(alg: string) {\r\n switch (alg.charAt(0)) {\r\n case 'R':\r\n return 'RSA';\r\n case 'E':\r\n return 'EC';\r\n default:\r\n throw new Error('Cannot infer kty from alg: ' + alg);\r\n }\r\n }\r\n\r\n calcHash(valueToHash: string, algorithm: string): Promise<string> {\r\n let hashAlg = new rs.KJUR.crypto.MessageDigest({ alg: algorithm });\r\n let result = hashAlg.digestString(valueToHash);\r\n let byteArrayAsString = this.toByteArrayAsString(result);\r\n return Promise.resolve(byteArrayAsString);\r\n }\r\n\r\n toByteArrayAsString(hexString: string) {\r\n let result = '';\r\n for (let i = 0; i < hexString.length; i += 2) {\r\n let hexDigit = hexString.charAt(i) + hexString.charAt(i + 1);\r\n let num = parseInt(hexDigit, 16);\r\n result += String.fromCharCode(num);\r\n }\r\n return result;\r\n }\r\n}",
|
40 | "import { InjectionToken } from '@angular/core';\r\nimport { AuthConfig } from './auth.config';\r\n\r\nexport const AUTH_CONFIG = new InjectionToken<AuthConfig>('AUTH_CONFIG');\r\n"
|
41 | ],
|
42 | "names": [
|
43 | "extendStatics",
|
44 | "d",
|
45 | "b",
|
46 | "Object",
|
47 | "setPrototypeOf",
|
48 | "__proto__",
|
49 | "Array",
|
50 | "p",
|
51 | "hasOwnProperty",
|
52 | "__extends",
|
53 | "__",
|
54 | "this",
|
55 | "constructor",
|
56 | "prototype",
|
57 | "create",
|
58 | "__awaiter",
|
59 | "thisArg",
|
60 | "_arguments",
|
61 | "P",
|
62 | "generator",
|
63 | "Promise",
|
64 | "resolve",
|
65 | "reject",
|
66 | "fulfilled",
|
67 | "value",
|
68 | "step",
|
69 | "next",
|
70 | "e",
|
71 | "rejected",
|
72 | "result",
|
73 | "done",
|
74 | "then",
|
75 | "apply",
|
76 | "__generator",
|
77 | "body",
|
78 | "f",
|
79 | "y",
|
80 | "t",
|
81 | "g",
|
82 | "_",
|
83 | "label",
|
84 | "sent",
|
85 | "trys",
|
86 | "ops",
|
87 | "verb",
|
88 | "throw",
|
89 | "return",
|
90 | "Symbol",
|
91 | "iterator",
|
92 | "n",
|
93 | "v",
|
94 | "op",
|
95 | "TypeError",
|
96 | "call",
|
97 | "pop",
|
98 | "length",
|
99 | "push",
|
100 | "__values",
|
101 | "o",
|
102 | "m",
|
103 | "i",
|
104 | "__read",
|
105 | "r",
|
106 | "ar",
|
107 | "error",
|
108 | "LoginOptions",
|
109 | "preventClearHashAfterLogin",
|
110 | "OAuthLogger",
|
111 | "OAuthStorage",
|
112 | "ReceivedTokens",
|
113 | "ValidationHandler",
|
114 | "AbstractValidationHandler",
|
115 | "validateAtHash",
|
116 | "params",
|
117 | "hashAlg",
|
118 | "inferHashAlgorithm",
|
119 | "idTokenHeader",
|
120 | "calcHash",
|
121 | "accessToken",
|
122 | "tokenHash",
|
123 | "_a",
|
124 | "leftMostHalf",
|
125 | "substr",
|
126 | "tokenHashBase64",
|
127 | "btoa",
|
128 | "atHash",
|
129 | "replace",
|
130 | "claimsAtHash",
|
131 | "idTokenClaims",
|
132 | "console",
|
133 | "jwtHeader",
|
134 | "alg",
|
135 | "match",
|
136 | "Error",
|
137 | "UrlHelperService",
|
138 | "getHashFragmentParams",
|
139 | "customHashFragment",
|
140 | "hash",
|
141 | "window",
|
142 | "location",
|
143 | "decodeURIComponent",
|
144 | "indexOf",
|
145 | "questionMarkPosition",
|
146 | "parseQueryString",
|
147 | "queryString",
|
148 | "pairs",
|
149 | "pair",
|
150 | "separatorIndex",
|
151 | "escapedKey",
|
152 | "escapedValue",
|
153 | "key",
|
154 | "data",
|
155 | "split",
|
156 | "type",
|
157 | "Injectable",
|
158 | "OAuthEvent",
|
159 | "OAuthSuccessEvent",
|
160 | "_super",
|
161 | "info",
|
162 | "_this",
|
163 | "tslib_1.__extends",
|
164 | "OAuthInfoEvent",
|
165 | "OAuthErrorEvent",
|
166 | "reason",
|
167 | "b64DecodeUnicode",
|
168 | "str",
|
169 | "base64",
|
170 | "atob",
|
171 | "map",
|
172 | "c",
|
173 | "charCodeAt",
|
174 | "toString",
|
175 | "slice",
|
176 | "join",
|
177 | "AuthConfig",
|
178 | "json",
|
179 | "clientId",
|
180 | "redirectUri",
|
181 | "postLogoutRedirectUri",
|
182 | "loginUrl",
|
183 | "scope",
|
184 | "resource",
|
185 | "rngUrl",
|
186 | "oidc",
|
187 | "requestAccessToken",
|
188 | "options",
|
189 | "issuer",
|
190 | "logoutUrl",
|
191 | "clearHashAfterLogin",
|
192 | "tokenEndpoint",
|
193 | "userinfoEndpoint",
|
194 | "responseType",
|
195 | "showDebugInformation",
|
196 | "silentRefreshRedirectUri",
|
197 | "silentRefreshMessagePrefix",
|
198 | "silentRefreshShowIFrame",
|
199 | "siletRefreshTimeout",
|
200 | "silentRefreshTimeout",
|
201 | "dummyClientSecret",
|
202 | "requireHttps",
|
203 | "strictDiscoveryDocumentValidation",
|
204 | "jwks",
|
205 | "customQueryParams",
|
206 | "silentRefreshIFrameName",
|
207 | "timeoutFactor",
|
208 | "sessionChecksEnabled",
|
209 | "sessionCheckIntervall",
|
210 | "sessionCheckIFrameUrl",
|
211 | "sessionCheckIFrameName",
|
212 | "disableAtHashCheck",
|
213 | "skipSubjectCheck",
|
214 | "useIdTokenHintForSilentRefresh",
|
215 | "skipIssuerCheck",
|
216 | "nonceStateSeparator",
|
217 | "useHttpBasicAuthForPasswordFlow",
|
218 | "openUri",
|
219 | "uri",
|
220 | "href",
|
221 | "assign",
|
222 | "WebHttpUrlEncodingCodec",
|
223 | "encodeKey",
|
224 | "k",
|
225 | "encodeURIComponent",
|
226 | "encodeValue",
|
227 | "decodeKey",
|
228 | "decodeValue",
|
229 | "OAuthService",
|
230 | "ngZone",
|
231 | "http",
|
232 | "storage",
|
233 | "tokenValidationHandler",
|
234 | "config",
|
235 | "urlHelper",
|
236 | "logger",
|
237 | "discoveryDocumentLoaded",
|
238 | "state",
|
239 | "eventsSubject",
|
240 | "Subject",
|
241 | "discoveryDocumentLoadedSubject",
|
242 | "grantTypesSupported",
|
243 | "inImplicitFlow",
|
244 | "discoveryDocumentLoaded$",
|
245 | "asObservable",
|
246 | "events",
|
247 | "configure",
|
248 | "setStorage",
|
249 | "sessionStorage",
|
250 | "setupRefreshTimer",
|
251 | "setupSessionCheck",
|
252 | "configChanged",
|
253 | "restartSessionChecksIfStillLoggedIn",
|
254 | "hasValidIdToken",
|
255 | "initSessionCheck",
|
256 | "restartRefreshTimerIfStillLoggedIn",
|
257 | "setupExpirationTimers",
|
258 | "pipe",
|
259 | "filter",
|
260 | "subscribe",
|
261 | "setupAutomaticSilentRefresh",
|
262 | "silentRefresh",
|
263 | "catch",
|
264 | "debug",
|
265 | "loadDiscoveryDocumentAndTryLogin",
|
266 | "loadDiscoveryDocument",
|
267 | "doc",
|
268 | "tryLogin",
|
269 | "loadDiscoveryDocumentAndLogin",
|
270 | "hasValidAccessToken",
|
271 | "initImplicitFlow",
|
272 | "args",
|
273 | "_i",
|
274 | "arguments",
|
275 | "validateUrlFromDiscoveryDocument",
|
276 | "url",
|
277 | "errors",
|
278 | "httpsCheck",
|
279 | "validateUrlForHttps",
|
280 | "issuerCheck",
|
281 | "validateUrlAgainstIssuer",
|
282 | "lcUrl",
|
283 | "toLowerCase",
|
284 | "startsWith",
|
285 | "clearAccessTokenTimer",
|
286 | "clearIdTokenTimer",
|
287 | "idTokenExp",
|
288 | "getIdTokenExpiration",
|
289 | "Number",
|
290 | "MAX_VALUE",
|
291 | "useAccessTokenExp",
|
292 | "getAccessTokenExpiration",
|
293 | "setupAccessTokenTimer",
|
294 | "setupIdTokenTimer",
|
295 | "expiration",
|
296 | "storedAt",
|
297 | "getAccessTokenStoredAt",
|
298 | "timeout",
|
299 | "calcTimeout",
|
300 | "runOutsideAngular",
|
301 | "accessTokenTimeoutSubscription",
|
302 | "of",
|
303 | "delay",
|
304 | "run",
|
305 | "getIdTokenStoredAt",
|
306 | "idTokenTimeoutSubscription",
|
307 | "unsubscribe",
|
308 | "_storage",
|
309 | "fullUrl",
|
310 | "endsWith",
|
311 | "get",
|
312 | "validateDiscoveryDocument",
|
313 | "authorization_endpoint",
|
314 | "end_session_endpoint",
|
315 | "grant_types_supported",
|
316 | "token_endpoint",
|
317 | "userinfo_endpoint",
|
318 | "jwksUri",
|
319 | "jwks_uri",
|
320 | "check_session_iframe",
|
321 | "loadJwks",
|
322 | "event",
|
323 | "discoveryDocument",
|
324 | "err",
|
325 | "warn",
|
326 | "fetchTokenUsingPasswordFlowAndLoadUserProfile",
|
327 | "userName",
|
328 | "password",
|
329 | "headers",
|
330 | "HttpHeaders",
|
331 | "fetchTokenUsingPasswordFlow",
|
332 | "loadUserProfile",
|
333 | "set",
|
334 | "getAccessToken",
|
335 | "existingClaims",
|
336 | "getIdentityClaims",
|
337 | "sub",
|
338 | "setItem",
|
339 | "JSON",
|
340 | "stringify",
|
341 | "HttpParams",
|
342 | "encoder",
|
343 | "header",
|
344 | "_b",
|
345 | "tslib_1.__values",
|
346 | "getOwnPropertyNames",
|
347 | "_c",
|
348 | "post",
|
349 | "tokenResponse",
|
350 | "storeAccessTokenResponse",
|
351 | "access_token",
|
352 | "refresh_token",
|
353 | "expires_in",
|
354 | "refreshToken",
|
355 | "getItem",
|
356 | "removeSilentRefreshEventListener",
|
357 | "silentRefreshPostMessageEventListener",
|
358 | "removeEventListener",
|
359 | "setupSilentRefreshEventListener",
|
360 | "expectedPrefix",
|
361 | "prefixedMessage",
|
362 | "message",
|
363 | "onLoginError",
|
364 | "onTokenReceived",
|
365 | "addEventListener",
|
366 | "noPrompt",
|
367 | "claims",
|
368 | "getIdToken",
|
369 | "document",
|
370 | "existingIframe",
|
371 | "getElementById",
|
372 | "removeChild",
|
373 | "silentRefreshSubject",
|
374 | "iframe",
|
375 | "createElement",
|
376 | "id",
|
377 | "createLoginUrl",
|
378 | "setAttribute",
|
379 | "style",
|
380 | "appendChild",
|
381 | "first",
|
382 | "success",
|
383 | "race",
|
384 | "tap",
|
385 | "toPromise",
|
386 | "canPerformSessionCheck",
|
387 | "getSessionState",
|
388 | "setupSessionCheckEventListener",
|
389 | "removeSessionCheckEventListener",
|
390 | "sessionCheckEventListener",
|
391 | "origin",
|
392 | "handleSessionUnchanged",
|
393 | "handleSessionChange",
|
394 | "handleSessionError",
|
395 | "stopSessionCheckTimer",
|
396 | "waitForSilentRefreshAfterSessionChange",
|
397 | "logOut",
|
398 | "display",
|
399 | "startSessionCheckTimer",
|
400 | "sessionCheckTimer",
|
401 | "setInterval",
|
402 | "checkSession",
|
403 | "bind",
|
404 | "clearInterval",
|
405 | "sessionState",
|
406 | "contentWindow",
|
407 | "postMessage",
|
408 | "loginHint",
|
409 | "customRedirectUri",
|
410 | "that",
|
411 | "createAndSaveNonce",
|
412 | "nonce",
|
413 | "seperationChar",
|
414 | "keys",
|
415 | "_d",
|
416 | "_e",
|
417 | "_f",
|
418 | "initImplicitFlowInternal",
|
419 | "additionalState",
|
420 | "addParams",
|
421 | "callOnTokenReceivedIfExists",
|
422 | "tokenParams",
|
423 | "idClaims",
|
424 | "idToken",
|
425 | "expiresIn",
|
426 | "grantedScopes",
|
427 | "Date",
|
428 | "now",
|
429 | "expiresInMilliSeconds",
|
430 | "expiresAt",
|
431 | "getTime",
|
432 | "parts",
|
433 | "nonceInState",
|
434 | "idx",
|
435 | "handleLoginError",
|
436 | "disableOAuth2StateCheck",
|
437 | "validateNonceForAccessToken",
|
438 | "fallbackAccessTokenExpirationTimeInSec",
|
439 | "processIdToken",
|
440 | "validationHandler",
|
441 | "storeIdToken",
|
442 | "storeSessionState",
|
443 | "savedNonce",
|
444 | "idTokenClaimsJson",
|
445 | "idTokenExpiresAt",
|
446 | "tokenParts",
|
447 | "headerJson",
|
448 | "padBase64",
|
449 | "parse",
|
450 | "claimsJson",
|
451 | "isArray",
|
452 | "aud",
|
453 | "every",
|
454 | "iat",
|
455 | "iss",
|
456 | "issuedAtMSec",
|
457 | "expiresAtMSec",
|
458 | "exp",
|
459 | "validationParams",
|
460 | "loadKeys",
|
461 | "checkAtHash",
|
462 | "atHashValid",
|
463 | "checkSignature",
|
464 | "idTokenHeaderJson",
|
465 | "getGrantedScopes",
|
466 | "scopes",
|
467 | "base64data",
|
468 | "getRefreshToken",
|
469 | "parseInt",
|
470 | "authorizationHeader",
|
471 | "noRedirectToLogoutUrl",
|
472 | "id_token",
|
473 | "removeItem",
|
474 | "postLogoutUrl",
|
475 | "createNonce",
|
476 | "text",
|
477 | "possible",
|
478 | "charAt",
|
479 | "Math",
|
480 | "floor",
|
481 | "random",
|
482 | "validateSignature",
|
483 | "NgZone",
|
484 | "HttpClient",
|
485 | "decorators",
|
486 | "Optional",
|
487 | "OAuthModuleConfig",
|
488 | "OAuthResourceServerConfig",
|
489 | "OAuthResourceServerErrorHandler",
|
490 | "OAuthNoopResourceServerErrorHandler",
|
491 | "handleError",
|
492 | "throwError",
|
493 | "DefaultOAuthInterceptor",
|
494 | "authStorage",
|
495 | "errorHandler",
|
496 | "moduleConfig",
|
497 | "checkUrl",
|
498 | "resourceServer",
|
499 | "allowedUrls",
|
500 | "find",
|
501 | "u",
|
502 | "intercept",
|
503 | "req",
|
504 | "handle",
|
505 | "sendAccessToken",
|
506 | "clone",
|
507 | "catchError",
|
508 | "NullValidationHandler",
|
509 | "createDefaultLogger",
|
510 | "createDefaultStorage",
|
511 | "OAuthModule",
|
512 | "forRoot",
|
513 | "validationHandlerClass",
|
514 | "ngModule",
|
515 | "providers",
|
516 | "provide",
|
517 | "useFactory",
|
518 | "useClass",
|
519 | "useValue",
|
520 | "HTTP_INTERCEPTORS",
|
521 | "multi",
|
522 | "NgModule",
|
523 | "imports",
|
524 | "CommonModule",
|
525 | "declarations",
|
526 | "exports",
|
527 | "JwksValidationHandler",
|
528 | "__spread",
|
529 | "concat",
|
530 | "allowedAlgorithms",
|
531 | "gracePeriodInSec",
|
532 | "retry",
|
533 | "kid",
|
534 | "kty_1",
|
535 | "alg2kty",
|
536 | "matchingKeys",
|
537 | "loadedKeys",
|
538 | "keyObj",
|
539 | "rs.KEYUTIL",
|
540 | "getKey",
|
541 | "validationOptions",
|
542 | "gracePeriod",
|
543 | "rs.KJUR",
|
544 | "jws",
|
545 | "JWS",
|
546 | "verifyJWT",
|
547 | "valueToHash",
|
548 | "algorithm",
|
549 | "crypto",
|
550 | "MessageDigest",
|
551 | "digestString",
|
552 | "byteArrayAsString",
|
553 | "toByteArrayAsString",
|
554 | "hexString",
|
555 | "hexDigit",
|
556 | "num",
|
557 | "String",
|
558 | "fromCharCode",
|
559 | "AUTH_CONFIG",
|
560 | "InjectionToken"
|
561 | ],
|
562 | "mappings": "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"
|
563 | }
|