angular-auth-oidc-client
Version:
Angular Lib for OpenID Connect & OAuth2
118 lines • 23.2 kB
JavaScript
import { HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { of, throwError } from 'rxjs';
import { catchError, retry, switchMap, tap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "../api/data.service";
import * as i2 from "../storage/storage-persistence.service";
import * as i3 from "../logging/logger.service";
import * as i4 from "../utils/url/url.service";
import * as i5 from "../iframe/check-session.service";
import * as i6 from "../flows/reset-auth-data.service";
import * as i7 from "../utils/redirect/redirect.service";
export class LogoffRevocationService {
constructor(dataService, storagePersistenceService, loggerService, urlService, checkSessionService, resetAuthDataService, redirectService) {
this.dataService = dataService;
this.storagePersistenceService = storagePersistenceService;
this.loggerService = loggerService;
this.urlService = urlService;
this.checkSessionService = checkSessionService;
this.resetAuthDataService = resetAuthDataService;
this.redirectService = redirectService;
}
// Logs out on the server and the local client.
// If the server state has changed, check session, then only a local logout.
logoff(config, allConfigs, authOptions) {
const { urlHandler, customParams } = authOptions || {};
this.loggerService.logDebug(config, 'logoff, remove auth ');
const endSessionUrl = this.getEndSessionUrl(config, customParams);
this.resetAuthDataService.resetAuthorizationData(config, allConfigs);
if (!endSessionUrl) {
this.loggerService.logDebug(config, 'only local login cleaned up, no end_session_endpoint');
return;
}
if (this.checkSessionService.serverStateChanged(config)) {
this.loggerService.logDebug(config, 'only local login cleaned up, server session has changed');
}
else if (urlHandler) {
urlHandler(endSessionUrl);
}
else {
this.redirectService.redirectTo(endSessionUrl);
}
}
logoffLocal(config, allConfigs) {
this.resetAuthDataService.resetAuthorizationData(config, allConfigs);
this.checkSessionService.stop();
}
logoffLocalMultiple(allConfigs) {
allConfigs.forEach((configuration) => this.logoffLocal(configuration, allConfigs));
}
// The refresh token and and the access token are revoked on the server. If the refresh token does not exist
// only the access token is revoked. Then the logout run.
logoffAndRevokeTokens(config, allConfigs, authOptions) {
const { revocationEndpoint } = this.storagePersistenceService.read('authWellKnownEndPoints', config) || {};
if (!revocationEndpoint) {
this.loggerService.logDebug(config, 'revocation endpoint not supported');
this.logoff(config, allConfigs, authOptions);
return of(null);
}
if (this.storagePersistenceService.getRefreshToken(config)) {
return this.revokeRefreshToken(config).pipe(switchMap((_) => this.revokeAccessToken(config)), catchError((error) => {
const errorMessage = `revoke token failed`;
this.loggerService.logError(config, errorMessage, error);
return throwError(() => new Error(errorMessage));
}), tap(() => this.logoff(config, allConfigs, authOptions)));
}
else {
return this.revokeAccessToken(config).pipe(catchError((error) => {
const errorMessage = `revoke accessToken failed`;
this.loggerService.logError(config, errorMessage, error);
return throwError(() => new Error(errorMessage));
}), tap(() => this.logoff(config, allConfigs, authOptions)));
}
}
// https://tools.ietf.org/html/rfc7009
// revokes an access token on the STS. If no token is provided, then the token from
// the storage is revoked. You can pass any token to revoke. This makes it possible to
// manage your own tokens. The is a public API.
revokeAccessToken(configuration, accessToken) {
const accessTok = accessToken || this.storagePersistenceService.getAccessToken(configuration);
const body = this.urlService.createRevocationEndpointBodyAccessToken(accessTok, configuration);
return this.sendRevokeRequest(configuration, body);
}
// https://tools.ietf.org/html/rfc7009
// revokes an refresh token on the STS. This is only required in the code flow with refresh tokens.
// If no token is provided, then the token from the storage is revoked. You can pass any token to revoke.
// This makes it possible to manage your own tokens.
revokeRefreshToken(configuration, refreshToken) {
const refreshTok = refreshToken || this.storagePersistenceService.getRefreshToken(configuration);
const body = this.urlService.createRevocationEndpointBodyRefreshToken(refreshTok, configuration);
return this.sendRevokeRequest(configuration, body);
}
getEndSessionUrl(configuration, customParams) {
const idToken = this.storagePersistenceService.getIdToken(configuration);
const { customParamsEndSessionRequest } = configuration;
const mergedParams = { ...customParamsEndSessionRequest, ...customParams };
return this.urlService.createEndSessionUrl(idToken, configuration, mergedParams);
}
sendRevokeRequest(configuration, body) {
const url = this.urlService.getRevocationEndpointUrl(configuration);
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
return this.dataService.post(url, body, configuration, headers).pipe(retry(2), switchMap((response) => {
this.loggerService.logDebug(configuration, 'revocation endpoint post response: ', response);
return of(response);
}), catchError((error) => {
const errorMessage = `Revocation request failed`;
this.loggerService.logError(configuration, errorMessage, error);
return throwError(() => new Error(errorMessage));
}));
}
}
LogoffRevocationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: LogoffRevocationService, deps: [{ token: i1.DataService }, { token: i2.StoragePersistenceService }, { token: i3.LoggerService }, { token: i4.UrlService }, { token: i5.CheckSessionService }, { token: i6.ResetAuthDataService }, { token: i7.RedirectService }], target: i0.ɵɵFactoryTarget.Injectable });
LogoffRevocationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: LogoffRevocationService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: LogoffRevocationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.DataService }, { type: i2.StoragePersistenceService }, { type: i3.LoggerService }, { type: i4.UrlService }, { type: i5.CheckSessionService }, { type: i6.ResetAuthDataService }, { type: i7.RedirectService }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nb2ZmLXJldm9jYXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItYXV0aC1vaWRjLWNsaWVudC9zcmMvbGliL2xvZ29mZi1yZXZva2UvbG9nb2ZmLXJldm9jYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQWMsRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7OztBQVluRSxNQUFNLE9BQU8sdUJBQXVCO0lBQ2xDLFlBQ21CLFdBQXdCLEVBQ3hCLHlCQUFvRCxFQUNwRCxhQUE0QixFQUM1QixVQUFzQixFQUN0QixtQkFBd0MsRUFDeEMsb0JBQTBDLEVBQzFDLGVBQWdDO1FBTmhDLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLDhCQUF5QixHQUF6Qix5QkFBeUIsQ0FBMkI7UUFDcEQsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0Qix3QkFBbUIsR0FBbkIsbUJBQW1CLENBQXFCO1FBQ3hDLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsb0JBQWUsR0FBZixlQUFlLENBQWlCO0lBQ2hELENBQUM7SUFFSiwrQ0FBK0M7SUFDL0MsNEVBQTRFO0lBQzVFLE1BQU0sQ0FBQyxNQUEyQixFQUFFLFVBQWlDLEVBQUUsV0FBeUI7UUFDOUYsTUFBTSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsR0FBRyxXQUFXLElBQUksRUFBRSxDQUFDO1FBRXZELElBQUksQ0FBQyxhQUFh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QUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFaEUsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQzs7b0hBeklVLHVCQUF1Qjt3SEFBdkIsdUJBQXVCOzJGQUF2Qix1QkFBdUI7a0JBRG5DLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBjYXRjaEVycm9yLCByZXRyeSwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IERhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vYXBpL2RhdGEuc2VydmljZSc7XHJcbmltcG9ydCB7IEF1dGhPcHRpb25zIH0gZnJvbSAnLi4vYXV0aC1vcHRpb25zJztcclxuaW1wb3J0IHsgT3BlbklkQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL2NvbmZpZy9vcGVuaWQtY29uZmlndXJhdGlvbic7XHJcbmltcG9ydCB7IFJlc2V0QXV0aERhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vZmxvd3MvcmVzZXQtYXV0aC1kYXRhLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDaGVja1Nlc3Npb25TZXJ2aWNlIH0gZnJvbSAnLi4vaWZyYW1lL2NoZWNrLXNlc3Npb24uc2VydmljZSc7XHJcbmltcG9ydCB7IExvZ2dlclNlcnZpY2UgfSBmcm9tICcuLi9sb2dnaW5nL2xvZ2dlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgU3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZSB9IGZyb20gJy4uL3N0b3JhZ2Uvc3RvcmFnZS1wZXJzaXN0ZW5jZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUmVkaXJlY3RTZXJ2aWNlIH0gZnJvbSAnLi4vdXRpbHMvcmVkaXJlY3QvcmVkaXJlY3Quc2VydmljZSc7XHJcbmltcG9ydCB7IFVybFNlcnZpY2UgfSBmcm9tICcuLi91dGlscy91cmwvdXJsLnNlcnZpY2UnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgTG9nb2ZmUmV2b2NhdGlvblNlcnZpY2Uge1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBkYXRhU2VydmljZTogRGF0YVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2U6IFN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlclNlcnZpY2U6IExvZ2dlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHVybFNlcnZpY2U6IFVybFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoZWNrU2Vzc2lvblNlcnZpY2U6IENoZWNrU2Vzc2lvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlc2V0QXV0aERhdGFTZXJ2aWNlOiBSZXNldEF1dGhEYXRhU2VydmljZSxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVkaXJlY3RTZXJ2aWNlOiBSZWRpcmVjdFNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIC8vIExvZ3Mgb3V0IG9uIHRoZSBzZXJ2ZXIgYW5kIHRoZSBsb2NhbCBjbGllbnQuXHJcbiAgLy8gSWYgdGhlIHNlcnZlciBzdGF0ZSBoYXMgY2hhbmdlZCwgY2hlY2sgc2Vzc2lvbiwgdGhlbiBvbmx5IGEgbG9jYWwgbG9nb3V0LlxyXG4gIGxvZ29mZihjb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb24sIGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXSwgYXV0aE9wdGlvbnM/OiBBdXRoT3B0aW9ucyk6IHZvaWQge1xyXG4gICAgY29uc3QgeyB1cmxIYW5kbGVyLCBjdXN0b21QYXJhbXMgfSA9IGF1dGhPcHRpb25zIHx8IHt9O1xyXG5cclxuICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1Zyhjb25maWcsICdsb2dvZmYsIHJlbW92ZSBhdXRoICcpO1xyXG5cclxuICAgIGNvbnN0IGVuZFNlc3Npb25VcmwgPSB0aGlzLmdldEVuZFNlc3Npb25VcmwoY29uZmlnLCBjdXN0b21QYXJhbXMpO1xyXG5cclxuICAgIHRoaXMucmVzZXRBdXRoRGF0YVNlcnZpY2UucmVzZXRBdXRob3JpemF0aW9uRGF0YShjb25maWcsIGFsbENvbmZpZ3MpO1xyXG5cclxuICAgIGlmICghZW5kU2Vzc2lvblVybCkge1xyXG4gICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoY29uZmlnLCAnb25seSBsb2NhbCBsb2dpbiBjbGVhbmVkIHVwLCBubyBlbmRfc2Vzc2lvbl9lbmRwb2ludCcpO1xyXG5cclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmNoZWNrU2Vzc2lvblNlcnZpY2Uuc2VydmVyU3RhdGVDaGFuZ2VkKGNvbmZpZykpIHtcclxuICAgICAgdGhpcy5sb2dnZXJTZXJ2aWNlLmxvZ0RlYnVnKGNvbmZpZywgJ29ubHkgbG9jYWwgbG9naW4gY2xlYW5lZCB1cCwgc2VydmVyIHNlc3Npb24gaGFzIGNoYW5nZWQnKTtcclxuICAgIH0gZWxzZSBpZiAodXJsSGFuZGxlcikge1xyXG4gICAgICB1cmxIYW5kbGVyKGVuZFNlc3Npb25VcmwpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5yZWRpcmVjdFNlcnZpY2UucmVkaXJlY3RUbyhlbmRTZXNzaW9uVXJsKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxvZ29mZkxvY2FsKGNvbmZpZzogT3BlbklkQ29uZmlndXJhdGlvbiwgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdKTogdm9pZCB7XHJcbiAgICB0aGlzLnJlc2V0QXV0aERhdGFTZXJ2aWNlLnJlc2V0QXV0aG9yaXphdGlvbkRhdGEoY29uZmlnLCBhbGxDb25maWdzKTtcclxuICAgIHRoaXMuY2hlY2tTZXNzaW9uU2VydmljZS5zdG9wKCk7XHJcbiAgfVxyXG5cclxuICBsb2dvZmZMb2NhbE11bHRpcGxlKGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXSk6IHZvaWQge1xyXG4gICAgYWxsQ29uZmlncy5mb3JFYWNoKChjb25maWd1cmF0aW9uKSA9PiB0aGlzLmxvZ29mZkxvY2FsKGNvbmZpZ3VyYXRpb24sIGFsbENvbmZpZ3MpKTtcclxuICB9XHJcblxyXG4gIC8vIFRoZSByZWZyZXNoIHRva2VuIGFuZCBhbmQgdGhlIGFjY2VzcyB0b2tlbiBhcmUgcmV2b2tlZCBvbiB0aGUgc2VydmVyLiBJZiB0aGUgcmVmcmVzaCB0b2tlbiBkb2VzIG5vdCBleGlzdFxyXG4gIC8vIG9ubHkgdGhlIGFjY2VzcyB0b2tlbiBpcyByZXZva2VkLiBUaGVuIHRoZSBsb2dvdXQgcnVuLlxyXG4gIGxvZ29mZkFuZFJldm9rZVRva2Vucyhjb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb24sIGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXSwgYXV0aE9wdGlvbnM/OiBBdXRoT3B0aW9ucyk6IE9ic2VydmFibGU8YW55PiB7XHJcbiAgICBjb25zdCB7IHJldm9jYXRpb25FbmRwb2ludCB9ID0gdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlYWQoJ2F1dGhXZWxsS25vd25FbmRQb2ludHMnLCBjb25maWcpIHx8IHt9O1xyXG5cclxuICAgIGlmICghcmV2b2NhdGlvbkVuZHBvaW50KSB7XHJcbiAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1Zyhjb25maWcsICdyZXZvY2F0aW9uIGVuZHBvaW50IG5vdCBzdXBwb3J0ZWQnKTtcclxuICAgICAgdGhpcy5sb2dvZmYoY29uZmlnLCBhbGxDb25maWdzLCBhdXRoT3B0aW9ucyk7XHJcblxyXG4gICAgICByZXR1cm4gb2YobnVsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRSZWZyZXNoVG9rZW4oY29uZmlnKSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5yZXZva2VSZWZyZXNoVG9rZW4oY29uZmlnKS5waXBlKFxyXG4gICAgICAgIHN3aXRjaE1hcCgoXykgPT4gdGhpcy5yZXZva2VBY2Nlc3NUb2tlbihjb25maWcpKSxcclxuICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYHJldm9rZSB0b2tlbiBmYWlsZWRgO1xyXG5cclxuICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihjb25maWcsIGVycm9yTWVzc2FnZSwgZXJyb3IpO1xyXG5cclxuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpKTtcclxuICAgICAgICB9KSxcclxuICAgICAgICB0YXAoKCkgPT4gdGhpcy5sb2dvZmYoY29uZmlnLCBhbGxDb25maWdzLCBhdXRoT3B0aW9ucykpXHJcbiAgICAgICk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy5yZXZva2VBY2Nlc3NUb2tlbihjb25maWcpLnBpcGUoXHJcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcclxuICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGByZXZva2UgYWNjZXNzVG9rZW4gZmFpbGVkYDtcclxuXHJcbiAgICAgICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRXJyb3IoY29uZmlnLCBlcnJvck1lc3NhZ2UsIGVycm9yKTtcclxuXHJcbiAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKSk7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgdGFwKCgpID0+IHRoaXMubG9nb2ZmKGNvbmZpZywgYWxsQ29uZmlncywgYXV0aE9wdGlvbnMpKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzcwMDlcclxuICAvLyByZXZva2VzIGFuIGFjY2VzcyB0b2tlbiBvbiB0aGUgU1RTLiBJZiBubyB0b2tlbiBpcyBwcm92aWRlZCwgdGhlbiB0aGUgdG9rZW4gZnJvbVxyXG4gIC8vIHRoZSBzdG9yYWdlIGlzIHJldm9rZWQuIFlvdSBjYW4gcGFzcyBhbnkgdG9rZW4gdG8gcmV2b2tlLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvXHJcbiAgLy8gbWFuYWdlIHlvdXIgb3duIHRva2Vucy4gVGhlIGlzIGEgcHVibGljIEFQSS5cclxuICByZXZva2VBY2Nlc3NUb2tlbihjb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uLCBhY2Nlc3NUb2tlbj86IGFueSk6IE9ic2VydmFibGU8YW55PiB7XHJcbiAgICBjb25zdCBhY2Nlc3NUb2sgPSBhY2Nlc3NUb2tlbiB8fCB0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0QWNjZXNzVG9rZW4oY29uZmlndXJhdGlvbik7XHJcbiAgICBjb25zdCBib2R5ID0gdGhpcy51cmxTZXJ2aWNlLmNyZWF0ZVJldm9jYXRpb25FbmRwb2ludEJvZHlBY2Nlc3NUb2tlbihhY2Nlc3NUb2ssIGNvbmZpZ3VyYXRpb24pO1xyXG5cclxuICAgIHJldHVybiB0aGlzLnNlbmRSZXZva2VSZXF1ZXN0KGNvbmZpZ3VyYXRpb24sIGJvZHkpO1xyXG4gIH1cclxuXHJcbiAgLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzcwMDlcclxuICAvLyByZXZva2VzIGFuIHJlZnJlc2ggdG9rZW4gb24gdGhlIFNUUy4gVGhpcyBpcyBvbmx5IHJlcXVpcmVkIGluIHRoZSBjb2RlIGZsb3cgd2l0aCByZWZyZXNoIHRva2Vucy5cclxuICAvLyBJZiBubyB0b2tlbiBpcyBwcm92aWRlZCwgdGhlbiB0aGUgdG9rZW4gZnJvbSB0aGUgc3RvcmFnZSBpcyByZXZva2VkLiBZb3UgY2FuIHBhc3MgYW55IHRva2VuIHRvIHJldm9rZS5cclxuICAvLyBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIG1hbmFnZSB5b3VyIG93biB0b2tlbnMuXHJcbiAgcmV2b2tlUmVmcmVzaFRva2VuKGNvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24sIHJlZnJlc2hUb2tlbj86IGFueSk6IE9ic2VydmFibGU8YW55PiB7XHJcbiAgICBjb25zdCByZWZyZXNoVG9rID0gcmVmcmVzaFRva2VuIHx8IHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRSZWZyZXNoVG9rZW4oY29uZmlndXJhdGlvbik7XHJcbiAgICBjb25zdCBib2R5ID0gdGhpcy51cmxTZXJ2aWNlLmNyZWF0ZVJldm9jYXRpb25FbmRwb2ludEJvZHlSZWZyZXNoVG9rZW4ocmVmcmVzaFRvaywgY29uZmlndXJhdGlvbik7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuc2VuZFJldm9rZVJlcXVlc3QoY29uZmlndXJhdGlvbiwgYm9keSk7XHJcbiAgfVxyXG5cclxuICBnZXRFbmRTZXNzaW9uVXJsKGNvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24sIGN1c3RvbVBhcmFtcz86IHsgW3A6IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3QgaWRUb2tlbiA9IHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRJZFRva2VuKGNvbmZpZ3VyYXRpb24pO1xyXG4gICAgY29uc3QgeyBjdXN0b21QYXJhbXNFbmRTZXNzaW9uUmVxdWVzdCB9ID0gY29uZmlndXJhdGlvbjtcclxuXHJcbiAgICBjb25zdCBtZXJnZWRQYXJhbXMgPSB7IC4uLmN1c3RvbVBhcmFtc0VuZFNlc3Npb25SZXF1ZXN0LCAuLi5jdXN0b21QYXJhbXMgfTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy51cmxTZXJ2aWNlLmNyZWF0ZUVuZFNlc3Npb25VcmwoaWRUb2tlbiwgY29uZmlndXJhdGlvbiwgbWVyZ2VkUGFyYW1zKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2VuZFJldm9rZVJlcXVlc3QoY29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbiwgYm9keTogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcclxuICAgIGNvbnN0IHVybCA9IHRoaXMudXJsU2VydmljZS5nZXRSZXZvY2F0aW9uRW5kcG9pbnRVcmwoY29uZmlndXJhdGlvbik7XHJcblxyXG4gICAgbGV0IGhlYWRlcnM6IEh0dHBIZWFkZXJzID0gbmV3IEh0dHBIZWFkZXJzKCk7XHJcblxyXG4gICAgaGVhZGVycyA9IGhlYWRlcnMuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZGF0YVNlcnZpY2UucG9zdCh1cmwsIGJvZHksIGNvbmZpZ3VyYXRpb24sIGhlYWRlcnMpLnBpcGUoXHJcbiAgICAgIHJldHJ5KDIpLFxyXG4gICAgICBzd2l0Y2hNYXAoKHJlc3BvbnNlOiBhbnkpID0+IHtcclxuICAgICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoY29uZmlndXJhdGlvbiwgJ3Jldm9jYXRpb24gZW5kcG9pbnQgcG9zdCByZXNwb25zZTogJywgcmVzcG9uc2UpO1xyXG5cclxuICAgICAgICByZXR1cm4gb2YocmVzcG9uc2UpO1xyXG4gICAgICB9KSxcclxuICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcclxuICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgUmV2b2NhdGlvbiByZXF1ZXN0IGZhaWxlZGA7XHJcblxyXG4gICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihjb25maWd1cmF0aW9uLCBlcnJvck1lc3NhZ2UsIGVycm9yKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IEVycm9yKGVycm9yTWVzc2FnZSkpO1xyXG4gICAgICB9KVxyXG4gICAgKTtcclxuICB9XHJcbn1cclxuIl19