angular-simple-oidc
Version:
Angular Library implementing Open Id Connect specification. Code Flow, Refresh Tokens, Session Management, Discovery Document.
998 lines (980 loc) • 110 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs'), require('angular-simple-oidc/config'), require('rxjs/operators'), require('angular-simple-oidc/events'), require('angular-simple-oidc/core'), require('@angular/common/http'), require('angular-simple-oidc/operators')) :
typeof define === 'function' && define.amd ? define('angular-simple-oidc', ['exports', '@angular/core', 'rxjs', 'angular-simple-oidc/config', 'rxjs/operators', 'angular-simple-oidc/events', 'angular-simple-oidc/core', '@angular/common/http', 'angular-simple-oidc/operators'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["angular-simple-oidc"] = {}, global.ng.core, global.rxjs, global["angular-simple-oidc"].config, global.rxjs.operators, global["angular-simple-oidc"].events, global["angular-simple-oidc"].core, global.ng.common.http, global["angular-simple-oidc"].operators));
})(this, (function (exports, i0, rxjs, config, operators, i4, i6, http, operators$1) { 'use strict';
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
var i4__namespace = /*#__PURE__*/_interopNamespace(i4);
var i6__namespace = /*#__PURE__*/_interopNamespace(i6);
var AUTH_CONFIG_REQUIRED_FIELDS = ['clientId', 'openIDProviderUrl'];
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (Object.prototype.hasOwnProperty.call(b, p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); };
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try {
step(generator.next(value));
}
catch (e) {
reject(e);
} }
function rejected(value) { try {
step(generator["throw"](value));
}
catch (e) {
reject(e);
} }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function () { if (t[0] & 1)
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
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;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
}
catch (e) {
op = [6, e];
y = 0;
}
finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
}
var __createBinding = Object.create ? (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
}) : (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
o[k2] = m[k];
});
function __exportStar(m, o) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
__createBinding(o, m, p);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
/** @deprecated */
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/** @deprecated */
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2)
for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar)
ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
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); }); }; }
function resume(n, v) { try {
step(g[n](v));
}
catch (e) {
settle(q[0][3], e);
} }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
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; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
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);
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); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
}
else {
cooked.raw = raw;
}
return cooked;
}
;
var __setModuleDefault = Object.create ? (function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o, v) {
o["default"] = v;
};
function __importStar(mod) {
if (mod && mod.__esModule)
return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
function __classPrivateFieldGet(receiver, state, kind, f) {
if (kind === "a" && !f)
throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
}
function __classPrivateFieldSet(receiver, state, value, kind, f) {
if (kind === "m")
throw new TypeError("Private method is not writable");
if (kind === "a" && !f)
throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
}
var TokenEndpointUnexpectedError = /** @class */ (function (_super) {
__extends(TokenEndpointUnexpectedError, _super);
function TokenEndpointUnexpectedError(context) {
return _super.call(this, "Token endpoint returned unexpected error", "token-endpoint-unexpected-error", context) || this;
}
return TokenEndpointUnexpectedError;
}(i6.SimpleOidcError));
var TokenEndpointError = /** @class */ (function (_super) {
__extends(TokenEndpointError, _super);
function TokenEndpointError(error, context) {
return _super.call(this, "Token endpoint returned error: " + error, "token-endpoint-" + error, context) || this;
// TODO: Use errors from https://tools.ietf.org/html/rfc6749#section-5.2
}
return TokenEndpointError;
}(i6.SimpleOidcError));
var AuthenticationConfigurationMissingError = /** @class */ (function (_super) {
__extends(AuthenticationConfigurationMissingError, _super);
function AuthenticationConfigurationMissingError() {
return _super.call(this, "Expected AUTH_CONFIG to be in Injector." +
"\nYou need to provide a configuration either with AngularSimpleOidc.forRoot() " +
"or by adding your own (Observable<AuthConfig> | AuthConfig) " +
"into the injector with the AUTH_CONFIG injection token.", "auth-config-missing", null) || this;
}
return AuthenticationConfigurationMissingError;
}(i6.SimpleOidcError));
var UserInfoNotSupportedError = /** @class */ (function (_super) {
__extends(UserInfoNotSupportedError, _super);
function UserInfoNotSupportedError(doc) {
return _super.call(this, "User Info is not supported, or it's URL was not in discovery document", "user-info-not-suppo", doc) || this;
}
return UserInfoNotSupportedError;
}(i6.SimpleOidcError));
var WINDOW_REF = new i0.InjectionToken('Angular Simple OIDC Window Reference');
var LOCAL_STORAGE_REF = new i0.InjectionToken('Angular Simple OIDC LocalStorage Reference');
function localStorageFactory() {
return localStorage;
}
var LOCAL_STORAGE_PROVIDER = {
provide: LOCAL_STORAGE_REF,
useFactory: localStorageFactory
};
function windowFactory() {
return window;
}
var WINDOW_PROVIDER = {
provide: WINDOW_REF,
useFactory: windowFactory
};
// Configuration
var AUTH_CONFIG_SERVICE = new i0.InjectionToken('AUTH_CONFIG');
var AUTH_CONFIG = new i0.InjectionToken('AUTH_CONFIG');
var defaultConfig$2 = {
discoveryDocumentUrl: "/.well-known/openid-configuration",
tokenCallbackRoute: 'oidc-token-callback',
tokenValidation: {
disableIdTokenIATValidation: false,
idTokenIATOffsetAllowed: 10 // seconds
},
enableAuthorizationCallbackAppInitializer: true
};
function getApplicationBaseUrl() {
var base = document.querySelector('base');
return base && base.href || '';
}
function authConfigFactory(configInput, configService, window, events) {
if (!configInput) {
throw new AuthenticationConfigurationMissingError();
}
var config$ = rxjs.isObservable(configInput) ? configInput : rxjs.of(configInput);
return function () { return config$.pipe(operators.map(function (config) {
if (config && config.openIDProviderUrl) {
// do not modify the provided objects.
return Object.assign(Object.assign({}, config), { openIDProviderUrl: config.openIDProviderUrl.toLowerCase() });
}
return config;
}), operators.tap(function (config) { return configService.configure(config, {
defaultConfig: Object.assign(Object.assign({}, defaultConfig$2), { baseUrl: getApplicationBaseUrl() }),
requiredFields: AUTH_CONFIG_REQUIRED_FIELDS
}); }), operators.catchError(function (e) {
// make sure this errors get logged.
console.error('Callback failed in AUTH_CONFIG_INITIALIZER');
console.error(e);
events.dispatchError(e);
// Do not prevent bootstrapping in order to be able to handle errors gracefully.
return rxjs.of(null);
}))
.toPromise(); };
}
var AUTH_CONFIG_INITIALIZER = {
multi: true,
provide: i0.APP_INITIALIZER,
deps: [
[new i0.Optional(), AUTH_CONFIG],
AUTH_CONFIG_SERVICE,
WINDOW_REF,
i4.EventsService
],
useFactory: authConfigFactory
};
var AUTH_CONFIG_SERVICE_PROVIDER = {
provide: AUTH_CONFIG_SERVICE,
useClass: config.ConfigService,
};
// @dynamic
var TokenStorageService = /** @class */ (function () {
function TokenStorageService(localStorage) {
this.localStorage = localStorage;
this.localStateSubject = new rxjs.BehaviorSubject(this.getCurrentLocalState());
}
Object.defineProperty(TokenStorageService.prototype, "currentState$", {
get: function () {
return this.localStateSubject.asObservable();
},
enumerable: false,
configurable: true
});
Object.defineProperty(TokenStorageService.prototype, "storage", {
get: function () {
return this.localStorage;
},
enumerable: false,
configurable: true
});
TokenStorageService.prototype.storePreAuthorizationState = function (authState) {
this.storage.setItem(i6.TokenStorageKeys.Nonce, authState.nonce);
this.storage.setItem(i6.TokenStorageKeys.State, authState.state);
this.storage.setItem(i6.TokenStorageKeys.CodeVerifier, authState.codeVerifier);
this.storage.setItem(i6.TokenStorageKeys.PreRedirectUrl, authState.preRedirectUrl);
var state = this.getCurrentLocalState();
this.localStateSubject.next(state);
return rxjs.of(state);
};
TokenStorageService.prototype.clearPreAuthorizationState = function () {
this.storage.removeItem(i6.TokenStorageKeys.Nonce);
this.storage.removeItem(i6.TokenStorageKeys.State);
this.storage.removeItem(i6.TokenStorageKeys.CodeVerifier);
this.storage.removeItem(i6.TokenStorageKeys.PreRedirectUrl);
var state = this.getCurrentLocalState();
this.localStateSubject.next(state);
return rxjs.of(state);
};
TokenStorageService.prototype.storeAuthorizationCode = function (authorizationCode, sessionState) {
this.storage.setItem(i6.TokenStorageKeys.AuthorizationCode, authorizationCode);
if (sessionState) {
this.storage.setItem(i6.TokenStorageKeys.SessionState, sessionState);
}
var state = this.getCurrentLocalState();
this.localStateSubject.next(state);
return rxjs.of(state);
};
TokenStorageService.prototype.storeOriginalIdToken = function (idToken) {
this.storage.setItem(i6.TokenStorageKeys.OriginalIdentityToken, idToken);
var state = this.getCurrentLocalState();
this.localStateSubject.next(state);
return rxjs.of(state);
};
TokenStorageService.prototype.storeTokens = function (tokens) {
this.storage.setItem(i6.TokenStorageKeys.IdentityToken, tokens.idToken);
this.storeJSON(i6.TokenStorageKeys.IdentityTokenDecoded, tokens.decodedIdToken);
this.storage.setItem(i6.TokenStorageKeys.AccessToken, tokens.accessToken);
if (tokens.accessTokenExpiresAt) {
this.storage.setItem(i6.TokenStorageKeys.AccessTokenExpiration, tokens.accessTokenExpiresAt.toString());
}
if (tokens.refreshToken) {
this.storage.setItem(i6.TokenStorageKeys.RefreshToken, tokens.refreshToken);
}
var state = this.getCurrentLocalState();
this.localStateSubject.next(state);
return rxjs.of(state);
};
TokenStorageService.prototype.removeAll = function () {
var e_1, _a;
try {
for (var _b = __values(Object.keys(i6.TokenStorageKeys)), _c = _b.next(); !_c.done; _c = _b.next()) {
var k = _c.value;
// We can't use clear since we could
// potentially delete keys which are not owned by us
this.storage.removeItem(i6.TokenStorageKeys[k]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return rxjs.of(this.getCurrentLocalState());
};
TokenStorageService.prototype.getCurrentLocalState = function () {
var state = {
nonce: this.storage.getItem(i6.TokenStorageKeys.Nonce),
state: this.storage.getItem(i6.TokenStorageKeys.State),
codeVerifier: this.storage.getItem(i6.TokenStorageKeys.CodeVerifier),
authorizationCode: this.storage.getItem(i6.TokenStorageKeys.AuthorizationCode),
sessionState: this.storage.getItem(i6.TokenStorageKeys.SessionState),
identityToken: this.storage.getItem(i6.TokenStorageKeys.IdentityToken),
originalIdentityToken: this.storage.getItem(i6.TokenStorageKeys.OriginalIdentityToken),
accessToken: this.storage.getItem(i6.TokenStorageKeys.AccessToken),
accessTokenExpiration: parseInt(this.storage.getItem(i6.TokenStorageKeys.AccessTokenExpiration), 10),
refreshToken: this.storage.getItem(i6.TokenStorageKeys.RefreshToken),
preRedirectUrl: this.storage.getItem(i6.TokenStorageKeys.PreRedirectUrl),
decodedIdentityToken: this.readJSON(i6.TokenStorageKeys.IdentityTokenDecoded)
};
return state;
};
TokenStorageService.prototype.storeJSON = function (key, obj) {
this.storage.setItem(key, JSON.stringify(obj));
};
TokenStorageService.prototype.readJSON = function (key) {
var json = this.storage.getItem(key);
return json ? JSON.parse(json) : null;
};
return TokenStorageService;
}());
TokenStorageService.decorators = [
{ type: i0.Injectable }
];
TokenStorageService.ctorParameters = function () { return [
{ type: Storage, decorators: [{ type: i0.Inject, args: [LOCAL_STORAGE_REF,] }] }
]; };
var defaultUrlRegExp = /^(\w+:\/\/[^/?]+)?(.*?)(\?.+)?$/;
var protocolRelativeUrlRegExp = /^(\/\/[^/?]+)(.*?)(\?.+)?$/;
function splitUrl(partsStr, _a) {
var protocolRelative = _a.protocolRelative;
var match = (protocolRelative && partsStr.match(protocolRelativeUrlRegExp)) ||
partsStr.match(defaultUrlRegExp) ||
[];
var beforePathname = match[1] || '';
var pathname = (match[2] || '')
// Remove leading slashes
.replace(/^\/+/, '')
// Remove trailing slashes
.replace(/\/+$/, '')
// Normalize consecutive slashes to just one
.replace(/\/+/g, '/');
var afterPathname = (match[3] || '');
return { beforePathname: beforePathname, pathname: pathname, afterPathname: afterPathname };
}
function urlJoin() {
var parts = [];
for (var _i = 0; _i < arguments.length; _i++) {
parts[_i] = arguments[_i];
}
var lastArg = parts[parts.length - 1];
var options;
// If last argument is an object, then it's the options
// Note that null is an object, so we verify if is truthy
if (lastArg && typeof lastArg === 'object') {
options = lastArg;
parts = parts.slice(0, -1);
}
// Parse options
options = Object.assign({ leadingSlash: true, trailingSlash: false, protocolRelative: false }, options);
// Join parts
var partsStr = parts
.filter(function (part) { return typeof part === 'string' || typeof part === 'number'; })
.join('/');
// Split the parts into beforePathname, pathname, and afterPathname
// (scheme://host)(/pathname)(?queryString)
var _a = splitUrl(partsStr, options), beforePathname = _a.beforePathname, pathname = _a.pathname, afterPathname = _a.afterPathname;
var url = '';
// Start with beforePathname if not empty (http://google.com)
if (beforePathname) {
url += beforePathname + (pathname ? '/' : '');
// Otherwise start with the leading slash
}
else if (options.leadingSlash) {
url += '/';
}
// Add pathname (foo/bar)
url += pathname;
// Add trailing slash
if (options.trailingSlash && !url.endsWith('/')) {
url += '/';
}
return url;
}
var ObtainDiscoveryDocumentError = /** @class */ (function (_super) {
__extends(ObtainDiscoveryDocumentError, _super);
function ObtainDiscoveryDocumentError(context) {
return _super.call(this, 'Failed to obtain discovery document', 'discovery-doc-fetch-failed', context) || this;
}
return ObtainDiscoveryDocumentError;
}(i6.SimpleOidcError));
var ObtainJWTKeysError = /** @class */ (function (_super) {
__extends(ObtainJWTKeysError, _super);
function ObtainJWTKeysError(context) {
return _super.call(this, 'Failed to obtain JWT Keys', 'jwt-keys-fetch-failed', context) || this;
}
return ObtainJWTKeysError;
}(i6.SimpleOidcError));
var DiscoveryDocumentObtainedEvent = /** @class */ (function (_super) {
__extends(DiscoveryDocumentObtainedEvent, _super);
function DiscoveryDocumentObtainedEvent(discoveryDocument) {
return _super.call(this, "Discovery Document Obtained", discoveryDocument) || this;
}
return DiscoveryDocumentObtainedEvent;
}(i4.SimpleOidcInfoEvent));
var OidcDiscoveryDocClient = /** @class */ (function () {
function OidcDiscoveryDocClient(config, http, events) {
var _this = this;
this.config = config;
this.http = http;
this.events = events;
this.current$ = this.config.current$
.pipe(operators.map(function (config) { return urlJoin(config.openIDProviderUrl, config.discoveryDocumentUrl); }), operators.tap(function (url) { return _this.events.dispatch(new i4.SimpleOidcInfoEvent('Obtaining discovery document', url)); }), operators.switchMap(function (url) { return _this.http.get(url); }), operators.tap(function (doc) { return _this.events.dispatch(new DiscoveryDocumentObtainedEvent(doc)); }), operators.catchError(function (e) { return rxjs.throwError(new ObtainDiscoveryDocumentError(e)); }), operators.take(1), operators.shareReplay());
this.jwtKeys$ = this.current$
.pipe(operators.tap(function (doc) { return _this.events.dispatch(new i4.SimpleOidcInfoEvent('Obtaining JWT Keys', doc.jwks_uri)); }), operators.switchMap(function (doc) { return _this.http.get(doc.jwks_uri); }), operators.tap(function (j) { return _this.events.dispatch(new i4.SimpleOidcInfoEvent('JWT Keys obtained', j)); }), operators.catchError(function (e) { return rxjs.throwError(new ObtainJWTKeysError(e)); }), operators.take(1), operators.shareReplay());
}
return OidcDiscoveryDocClient;
}());
OidcDiscoveryDocClient.decorators = [
{ type: i0.Injectable }
];
OidcDiscoveryDocClient.ctorParameters = function () { return [
{ type: config.ConfigService, decorators: [{ type: i0.Inject, args: [AUTH_CONFIG_SERVICE,] }] },
{ type: http.HttpClient },
{ type: i4.EventsService }
]; };
var TokensObtainedEvent = /** @class */ (function (_super) {
__extends(TokensObtainedEvent, _super);
function TokensObtainedEvent(tokens) {
return _super.call(this, "Tokens obtained", tokens) || this;
}
return TokensObtainedEvent;
}(i4.SimpleOidcInfoEvent));
var TokensValidatedEvent = /** @class */ (function (_super) {
__extends(TokensValidatedEvent, _super);
function TokensValidatedEvent(tokens) {
return _super.call(this, "Tokens validated", tokens) || this;
}
return TokensValidatedEvent;
}(i4.SimpleOidcInfoEvent));
var TokensReadyEvent = /** @class */ (function (_super) {
__extends(TokensReadyEvent, _super);
function TokensReadyEvent(tokens) {
return _super.call(this, "Tokens are ready to be used (validated and stored)", tokens) || this;
}
return TokensReadyEvent;
}(i4.SimpleOidcInfoEvent));
var AccessTokenExpiredEvent = /** @class */ (function (_super) {
__extends(AccessTokenExpiredEvent, _super);
function AccessTokenExpiredEvent(payload) {
return _super.call(this, "Access token has expired", payload) || this;
}
return AccessTokenExpiredEvent;
}(i4.SimpleOidcInfoEvent));
var AccessTokenExpiringEvent = /** @class */ (function (_super) {
__extends(AccessTokenExpiringEvent, _super);
function AccessTokenExpiringEvent(payload) {
return _super.call(this, "Access token is almost expired", payload) || this;
}
return AccessTokenExpiringEvent;
}(i4.SimpleOidcInfoEvent));
var UserInfoObtainedEvent = /** @class */ (function (_super) {
__extends(UserInfoObtainedEvent, _super);
function UserInfoObtainedEvent(payload) {
return _super.call(this, "Obtained User Profile", payload) || this;
}
return UserInfoObtainedEvent;
}(i4.SimpleOidcInfoEvent));
var TokenEndpointClientService = /** @class */ (function () {
function TokenEndpointClientService(http, discoveryDocumentClient, tokenValidation, tokenHelper, events) {
this.http = http;
this.discoveryDocumentClient = discoveryDocumentClient;
this.tokenValidation = tokenValidation;
this.tokenHelper = tokenHelper;
this.events = events;
}
TokenEndpointClientService.prototype.call = function (payload) {
var _this = this;
var headers = new http.HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded');
return this.discoveryDocumentClient.current$
.pipe(operators.take(1), operators.switchMap(function (_a) {
var token_endpoint = _a.token_endpoint;
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Executing Token Endpoint", { url: token_endpoint, payload: payload }));
return _this.http.post(token_endpoint, payload, { headers: headers });
}), operators.tap({
error: function (e) {
if (e instanceof i6.SimpleOidcError) {
return;
}
if (e.status === 400) {
// https://tools.ietf.org/html/rfc6749#section-5.2
throw new TokenEndpointError(e.error.error, e);
}
else {
throw new TokenEndpointUnexpectedError(e);
}
}
}), operators.map(function (response) {
var expiresAt;
if (response.expires_in) {
expiresAt = _this.tokenHelper.getExpirationFromExpiresIn(response.expires_in);
}
else {
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Token Response did not contain expires_in", response));
}
var decodedToken;
if (response.id_token) {
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Validating Identity Token format", response.id_token));
_this.tokenValidation.validateIdTokenFormat(response.id_token);
decodedToken = _this.tokenHelper.getPayloadFromToken(response.id_token);
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Identity Token Payload decoded", decodedToken));
}
else {
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Token Response did not contain id_token", response));
}
var result = {
accessToken: response.access_token,
accessTokenExpiresIn: response.expires_in,
accessTokenExpiresAt: expiresAt ? expiresAt.getTime() : null,
error: response.error,
idToken: response.id_token,
refreshToken: response.refresh_token,
decodedIdToken: decodedToken
};
_this.events.dispatch(new TokensObtainedEvent(result));
return result;
}));
};
return TokenEndpointClientService;
}());
TokenEndpointClientService.decorators = [
{ type: i0.Injectable }
];
TokenEndpointClientService.ctorParameters = function () { return [
{ type: http.HttpClient },
{ type: OidcDiscoveryDocClient },
{ type: i6.TokenValidationService },
{ type: i6.TokenHelperService },
{ type: i4.EventsService }
]; };
var DynamicIframe = /** @class */ (function () {
function DynamicIframe(document) {
this.document = document;
this.handle = this.document.createElement('iframe');
}
DynamicIframe.prototype.appendTo = function (e) {
e.appendChild(this.handle);
return this;
};
DynamicIframe.prototype.appendToBody = function () {
this.appendTo(this.document.body);
return this;
};
DynamicIframe.prototype.setSource = function (url) {
this.handle.src = url;
return this;
};
DynamicIframe.prototype.hide = function () {
this.handle.style.display = 'none';
return this;
};
DynamicIframe.prototype.postMessage = function (msg, origin) {
this.handle.contentWindow.postMessage(msg, origin);
return this;
};
DynamicIframe.prototype.remove = function () {
// iframe may not have been appended.
if (this.handle.parentElement) {
this.handle.parentElement.removeChild(this.handle);
}
return this;
};
return DynamicIframe;
}());
// @dynamic
var DynamicIframeService = /** @class */ (function () {
function DynamicIframeService(window) {
this.window = window;
this.pending = [];
}
DynamicIframeService.prototype.create = function () {
var frame = new DynamicIframe(this.window.document);
this.pending.push(frame);
return frame;
};
return DynamicIframeService;
}());
DynamicIframeService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function DynamicIframeService_Factory() { return new DynamicIframeService(i0__namespace.ɵɵinject(WINDOW_REF)); }, token: DynamicIframeService, providedIn: "root" });
DynamicIframeService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] }
];
DynamicIframeService.ctorParameters = function () { return [
{ type: Window, decorators: [{ type: i0.Inject, args: [WINDOW_REF,] }] }
]; };
// @dynamic
var OidcCodeFlowClient = /** @class */ (function () {
function OidcCodeFlowClient(window, config, discoveryDocumentClient, tokenStorage, tokenValidation, tokenUrl, tokenEndpointClient, events, dynamicIframe) {
this.window = window;
this.config = config;
this.discoveryDocumentClient = discoveryDocumentClient;
this.tokenStorage = tokenStorage;
this.tokenValidation = tokenValidation;
this.tokenUrl = tokenUrl;
this.tokenEndpointClient = tokenEndpointClient;
this.events = events;
this.dynamicIframe = dynamicIframe;
}
OidcCodeFlowClient.prototype.startCodeFlow = function (options) {
var _this = this;
if (options === void 0) { options = {}; }
var opts = Object.assign({}, options);
if (!opts.returnUrlAfterCallback) {
opts.returnUrlAfterCallback = this.window.location.href;
}
return this.config.current$
.pipe(operators.map(function (config) { return urlJoin(config.baseUrl, config.tokenCallbackRoute); }), operators.switchMap(function (redirectUri) { return _this.generateCodeFlowMetadata({ redirectUri: redirectUri }); }), operators.tap(function () { return _this.events.dispatch(new i4.SimpleOidcInfoEvent("Starting Code Flow")); }), operators.switchMap(function (result) {
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Authorize URL generated", result));
return _this.tokenStorage.storePreAuthorizationState({
nonce: result.nonce,
state: result.state,
codeVerifier: result.codeVerifier,
preRedirectUrl: opts.returnUrlAfterCallback
}).pipe(operators.tap(function (state) {
_this.events.dispatch(new i4.SimpleOidcInfoEvent("Pre-authorize state stored", state));
_this.redirectToUrl(result.url);
}));
}), operators.take(1));
};
OidcCodeFlowClient.prototype.generateCodeFlowMetadata = function (params) {
var _this = this;
return this.discoveryDocumentClient.current$
.pipe(operators.withLatestFrom(this.config.current$), operators.map(function (_a) {
var _b = __read(_a, 2), discoveryDocument = _b[0], config = _b[1];
return _this.tokenUrl.createAuthorizeUrl(discoveryDocument.authorization_endpoint, Object.assign(Object.assign({ clientId: config.clientId, scope: config.scope, responseType: 'code' }, config.acrValues && { acrValues: config.acrValues }), params));
}), operators.take(1));
};
OidcCodeFlowClient.prototype.parseCodeFlowCallbackParams = function (href) {
try {
var result = this.tokenUrl.parseAuthorizeCallbackParamsFromUrl(href);
return Object.assign(Object.assign({}, result), { href: href });
}
catch (error) {
throw new i6.AuthorizationCallbackFormatError(error);
}
};
OidcCodeFlowClient.prototype.validateCodeFlowCallback = function (params, localState) {
var href = params.href, code = params.code, state = params.state, error = params.error;
this.events.dispatch(new i4.SimpleOidcInfoEvent("Validating URL params", { code: code, state: state, error: error, href: href }));
this.tokenValidation.validateAuthorizeCallbackFormat(code, state, error, href);
this.events.dispatch(new i4.SimpleOidcInfoEvent("Validating state vs local state", { localState: localState, state: state }));
this.tokenValidation.validateAuthorizeCallbackState(localState, state);
this.events.dispatch(new i4.SimpleOidcInfoEvent("Obtained authorization code.", { code: code, state: state }));
};
OidcCodeFlowClient.prototype.codeFlowCallback = function (href, redirectUri, metadata) {
var _this = this;
var params = this.parseCodeFlowCallbackParams(href);
this.validateCodeFlowCallback(params, metadata.state);
return this.tokenStorage.storeAuthorizationCode(params.code, params.sessionState)
.pipe(operators.switchMap(function () { return _this.config.current$; }), operators.switchMap(function (authConfig) {
var payload = _this.tokenUrl.createAuthorizationCodeRequestPayload({
clientId: authConfig.clientId,
clientSecret: authConfig.clientSecret,
scope: authConfig.scope,
redirectUri: redirectUri,
code: params.code,
codeVerifier: metadata.codeVerifier,
});
return _this.requestTokenWithAuthCode(payload, metadata.nonce);
}));
};
OidcCodeFlowClient.prototype.currentWindowCodeFlowCallback = function () {
var _this = this;
return this.tokenStorage.currentState$
.pipe(operators.take(1), // we will be trigger currentState$ below
operators.tap(function () { return _this.events.dispatch(new i4.SimpleOidcInfoEvent("Starting Code Flow callback")); }), operators.withLatestFrom(this.config.current$), operators.map(function (_a) {
var _b = __read(_a, 2), localState = _b[0], config = _b[1];
var redirectUri = urlJoin(config.baseUrl, config.tokenCallbackRoute);
return {
localState: localState,
redirectUri: redirectUri
};
}), operators.switchMap(function (_a) {
var localState = _a.localState, redirectUri = _a.redirectUri;
return _this.codeFlowCallback(_this.window.location.href, redirectUri, localState).pipe(operators.tap(function () { return _this.historyChangeUrl(localState.preRedirectUrl); }));
}), operators.take(1));
};
OidcCodeFlowClient.prototype.requestTokenWithAuthCode = function (payload, nonce) {
var _this = this;
// The discovery document for issuer
var discoveryDocument$ = this.discoveryDocumentClient.current$
.pipe(operators.take(1));
// JWT Keys to validate id token signature
var jwtKeys$ = this.discoveryDocumentClient.jwtKeys$
.pipe(operators.take(1));
return this.tokenEndpointClient.call(payload)
.pipe(operators.tap(function () { return _this.events.dispatch(new i4.SimpleOidcInfoEvent("Requesting token using authorization code", payload)); }), operators.withLatestFrom(discoveryDocument$, jwtKeys$, this.config.current$), operators.take(1), operators.tap(function (_a) {
var _b = __read(_a, 4), result = _b[0], discoveryDocument = _b[1], jwtKeys = _b[2], config = _b[3];
_this.events.dispatch(new i4.SimpleOidcInfoEvent('Validating identity token..', {
result: result,
nonce: nonce,
discoveryDocument: discoveryDocument,
jwtKeys: jwtKeys
}));
_this.tokenValidation.validateIdToken(config.clientId, result.idToken, result.decodedIdToken, nonce, discoveryDocument, jwtKeys, config.tokenValidation);
}), operators.tap(function (_a) {
var _b = __read(_a, 1), result = _b[0];
_this.events.dispatch(new i4.SimpleOidcInfoEvent('Validating access token..', result));
_this.tokenValidation.validateAccessToken(result.accessToken, result.decodedIdToken.at_hash);
}), operators$1.switchTap(function () {
_this.events.dispatch(new i4.SimpleOidcInfoEvent('Clearing pre-authorize state..'));
return _this.tokenStorage.clearPreAuthorizationState();
}), operators$1.switchTap(function (_a) {
var _b = __read(_a, 1), result = _b[0];
_this.events.dispatch(new TokensValidatedEvent(result));
_this.events.dispatch(new i4.SimpleOidcInfoEvent('Storing tokens..', result));
return _this.tokenStorage.storeTokens(result);
}), operators$1.switchTap(function (_a) {
var _b = __read(_a, 1), result = _b[0];
_this.events.dispatch(new i4.SimpleOidcInfoEvent('Storing original Identity Token..', result.idToken));
return _this.tokenStorage.storeOriginalIdToken(result.idToken);
}), operators.map(function (_a) {
var _b = __read(_a, 1), result = _b[0];
return result;
}), operators.tap(function (result) { return _this.events.dispatch(new TokensReadyEvent(result)); }));
};
OidcCodeFlowClient.prototype.redirectToUrl = function (url) {
this.events.dispatch(new i4.SimpleOidcInfoEvent("Redirecting", url));
this.window.location.href = url;
};
OidcCodeFlowClient.prototype.historyChangeUrl = function (url) {
if (this.window.history) {
this.events.dispatch(new i4.SimpleOidcInfoEvent("Changing URL with history API", url));
this.window.history.pushState({}, null, url);
}
else {
this.redirectToUrl(url);
}
};
return OidcCodeFlowClient;
}());
OidcCodeFlowClient.decorators = [
{ type: i0.Injectab