angular-auth-oidc-client
Version:
Angular Lib for OpenID Connect & OAuth2
102 lines • 17.9 kB
JavaScript
import { HttpHeaders } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { of, throwError, timer } from 'rxjs';
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service';
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
import { UrlService } from '../../utils/url/url.service';
import { TokenValidationService } from '../../validation/token-validation.service';
import { FlowsDataService } from '../flows-data.service';
import { isNetworkError } from './error-helper';
import * as i0 from "@angular/core";
export class CodeFlowCallbackHandlerService {
constructor() {
this.urlService = inject(UrlService);
this.loggerService = inject(LoggerService);
this.tokenValidationService = inject(TokenValidationService);
this.flowsDataService = inject(FlowsDataService);
this.storagePersistenceService = inject(StoragePersistenceService);
this.dataService = inject(DataService);
}
// STEP 1 Code Flow
codeFlowCallback(urlToCheck, config) {
const code = this.urlService.getUrlParameter(urlToCheck, 'code');
const state = this.urlService.getUrlParameter(urlToCheck, 'state');
const sessionState = this.urlService.getUrlParameter(urlToCheck, 'session_state');
if (!state) {
this.loggerService.logDebug(config, 'no state in url');
return throwError(() => new Error('no state in url'));
}
if (!code) {
this.loggerService.logDebug(config, 'no code in url');
return throwError(() => new Error('no code in url'));
}
this.loggerService.logDebug(config, 'running validation for callback', urlToCheck);
const initialCallbackContext = {
code,
refreshToken: '',
state,
sessionState,
authResult: null,
isRenewProcess: false,
jwtKeys: null,
validationResult: null,
existingIdToken: null,
};
return of(initialCallbackContext);
}
// STEP 2 Code Flow // Code Flow Silent Renew starts here
codeFlowCodeRequest(callbackContext, config) {
const authStateControl = this.flowsDataService.getAuthStateControl(config);
const isStateCorrect = this.tokenValidationService.validateStateFromHashCallback(callbackContext.state, authStateControl, config);
if (!isStateCorrect) {
return throwError(() => new Error('codeFlowCodeRequest incorrect state'));
}
const authWellknownEndpoints = this.storagePersistenceService.read('authWellKnownEndPoints', config);
const tokenEndpoint = authWellknownEndpoints?.tokenEndpoint;
if (!tokenEndpoint) {
return throwError(() => new Error('Token Endpoint not defined'));
}
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
const bodyForCodeFlow = this.urlService.createBodyForCodeFlowCodeRequest(callbackContext.code, config, config?.customParamsCodeRequest);
return this.dataService
.post(tokenEndpoint, bodyForCodeFlow, config, headers)
.pipe(switchMap((response) => {
if (response) {
const authResult = {
...response,
state: callbackContext.state,
session_state: callbackContext.sessionState,
};
callbackContext.authResult = authResult;
}
return of(callbackContext);
}), retryWhen((error) => this.handleRefreshRetry(error, config)), catchError((error) => {
const { authority } = config;
const errorMessage = `OidcService code request ${authority}`;
this.loggerService.logError(config, errorMessage, error);
return throwError(() => new Error(errorMessage));
}));
}
handleRefreshRetry(errors, config) {
return errors.pipe(mergeMap((error) => {
// retry token refresh if there is no internet connection
if (isNetworkError(error)) {
const { authority, refreshTokenRetryInSeconds } = config;
const errorMessage = `OidcService code request ${authority} - no internet connection`;
this.loggerService.logWarning(config, errorMessage, error);
return timer((refreshTokenRetryInSeconds ?? 0) * 1000);
}
return throwError(() => error);
}));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CodeFlowCallbackHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CodeFlowCallbackHandlerService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CodeFlowCallbackHandlerService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZS1mbG93LWNhbGxiYWNrLWhhbmRsZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItYXV0aC1vaWRjLWNsaWVudC9zcmMvbGliL2Zsb3dzL2NhbGxiYWNrLWhhbmRsaW5nL2NvZGUtZmxvdy1jYWxsYmFjay1oYW5kbGVyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBYyxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6RCxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXJELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUN0RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFFbkYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDekQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUdoRCxNQUFNLE9BQU8sOEJBQThCO0lBRDNDO1FBRW1CLGVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFaEMsa0JBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFdEMsMkJBQXNCLEdBQUcs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T0FBTyxNQUFNLENBQUMsSUFBSSxDQUNoQixRQUFRLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNqQix5REFBeUQ7WUFDekQsSUFBSSxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsTUFBTSxFQUFFLFNBQVMsRUFBRSwwQkFBMEIsRUFBRSxHQUFHLE1BQU0sQ0FBQztnQkFDekQsTUFBTSxZQUFZLEdBQUcsNEJBQTRCLFNBQVMsMkJBQTJCLENBQUM7Z0JBRXRGLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBRTNELE9BQU8sS0FBSyxDQUFDLENBQUMsMEJBQTBCLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDekQsQ0FBQztZQUVELE9BQU8sVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDOzhHQWhKVSw4QkFBOEI7a0hBQTlCLDhCQUE4QixjQURqQixNQUFNOzsyRkFDbkIsOEJBQThCO2tCQUQxQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBIZWFkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciwgdGltZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1lcmdlTWFwLCByZXRyeVdoZW4sIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vYXBpL2RhdGEuc2VydmljZSc7XG5pbXBvcnQgeyBPcGVuSWRDb25maWd1cmF0aW9uIH0gZnJvbSAnLi4vLi4vY29uZmlnL29wZW5pZC1jb25maWd1cmF0aW9uJztcbmltcG9ydCB7IExvZ2dlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9sb2dnaW5nL2xvZ2dlci5zZXJ2aWNlJztcbmltcG9ydCB7IFN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zdG9yYWdlL3N0b3JhZ2UtcGVyc2lzdGVuY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBVcmxTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvdXJsL3VybC5zZXJ2aWNlJztcbmltcG9ydCB7IFRva2VuVmFsaWRhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi92YWxpZGF0aW9uL3Rva2VuLXZhbGlkYXRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBBdXRoUmVzdWx0LCBDYWxsYmFja0NvbnRleHQgfSBmcm9tICcuLi9jYWxsYmFjay1jb250ZXh0JztcbmltcG9ydCB7IEZsb3dzRGF0YVNlcnZpY2UgfSBmcm9tICcuLi9mbG93cy1kYXRhLnNlcnZpY2UnO1xuaW1wb3J0IHsgaXNOZXR3b3JrRXJyb3IgfSBmcm9tICcuL2Vycm9yLWhlbHBlcic7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQ29kZUZsb3dDYWxsYmFja0hhbmRsZXJTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSB1cmxTZXJ2aWNlID0gaW5qZWN0KFVybFNlcnZpY2UpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyU2VydmljZSA9IGluamVjdChMb2dnZXJTZXJ2aWNlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHRva2VuVmFsaWRhdGlvblNlcnZpY2UgPSBpbmplY3QoVG9rZW5WYWxpZGF0aW9uU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBmbG93c0RhdGFTZXJ2aWNlID0gaW5qZWN0KEZsb3dzRGF0YVNlcnZpY2UpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZSA9IGluamVjdChcbiAgICBTdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlXG4gICk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkYXRhU2VydmljZSA9IGluamVjdChEYXRhU2VydmljZSk7XG5cbiAgLy8gU1RFUCAxIENvZGUgRmxvd1xuICBjb2RlRmxvd0NhbGxiYWNrKFxuICAgIHVybFRvQ2hlY2s6IHN0cmluZyxcbiAgICBjb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb25cbiAgKTogT2JzZXJ2YWJsZTxDYWxsYmFja0NvbnRleHQ+IHtcbiAgICBjb25zdCBjb2RlID0gdGhpcy51cmxTZXJ2aWNlLmdldFVybFBhcmFtZXRlcih1cmxUb0NoZWNrLCAnY29kZScpO1xuICAgIGNvbnN0IHN0YXRlID0gdGhpcy51cmxTZXJ2aWNlLmdldFVybFBhcmFtZXRlcih1cmxUb0NoZWNrLCAnc3RhdGUnKTtcbiAgICBjb25zdCBzZXNzaW9uU3RhdGUgPSB0aGlzLnVybFNlcnZpY2UuZ2V0VXJsUGFyYW1ldGVyKFxuICAgICAgdXJsVG9DaGVjayxcbiAgICAgICdzZXNzaW9uX3N0YXRlJ1xuICAgICk7XG5cbiAgICBpZiAoIXN0YXRlKSB7XG4gICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoY29uZmlnLCAnbm8gc3RhdGUgaW4gdXJsJyk7XG5cbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcignbm8gc3RhdGUgaW4gdXJsJykpO1xuICAgIH1cblxuICAgIGlmICghY29kZSkge1xuICAgICAgdGhpcy5sb2dnZXJTZXJ2aWNlLmxvZ0RlYnVnKGNvbmZpZywgJ25vIGNvZGUgaW4gdXJsJyk7XG5cbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcignbm8gY29kZSBpbiB1cmwnKSk7XG4gICAgfVxuXG4gICAgdGhpcy5sb2dnZXJTZXJ2aWNlLmxvZ0RlYnVnKFxuICAgICAgY29uZmlnLFxuICAgICAgJ3J1bm5pbmcgdmFsaWRhdGlvbiBmb3IgY2FsbGJhY2snLFxuICAgICAgdXJsVG9DaGVja1xuICAgICk7XG5cbiAgICBjb25zdCBpbml0aWFsQ2FsbGJhY2tDb250ZXh0OiBDYWxsYmFja0NvbnRleHQgPSB7XG4gICAgICBjb2RlLFxuICAgICAgcmVmcmVzaFRva2VuOiAnJyxcbiAgICAgIHN0YXRlLFxuICAgICAgc2Vzc2lvblN0YXRlLFxuICAgICAgYXV0aFJlc3VsdDogbnVsbCxcbiAgICAgIGlzUmVuZXdQcm9jZXNzOiBmYWxzZSxcbiAgICAgIGp3dEtleXM6IG51bGwsXG4gICAgICB2YWxpZGF0aW9uUmVzdWx0OiBudWxsLFxuICAgICAgZXhpc3RpbmdJZFRva2VuOiBudWxsLFxuICAgIH07XG5cbiAgICByZXR1cm4gb2YoaW5pdGlhbENhbGxiYWNrQ29udGV4dCk7XG4gIH1cblxuICAvLyBTVEVQIDIgQ29kZSBGbG93IC8vICBDb2RlIEZsb3cgU2lsZW50IFJlbmV3IHN0YXJ0cyBoZXJlXG4gIGNvZGVGbG93Q29kZVJlcXVlc3QoXG4gICAgY2FsbGJhY2tDb250ZXh0OiBDYWxsYmFja0NvbnRleHQsXG4gICAgY29uZmlnOiBPcGVuSWRDb25maWd1cmF0aW9uXG4gICk6IE9ic2VydmFibGU8Q2FsbGJhY2tDb250ZXh0PiB7XG4gICAgY29uc3QgYXV0aFN0YXRlQ29udHJvbCA9IHRoaXMuZmxvd3NEYXRhU2VydmljZS5nZXRBdXRoU3RhdGVDb250cm9sKGNvbmZpZyk7XG4gICAgY29uc3QgaXNTdGF0ZUNvcnJlY3QgPVxuICAgICAgdGhpcy50b2tlblZhbGlkYXRpb25TZXJ2aWNlLnZhbGlkYXRlU3RhdGVGcm9tSGFzaENhbGxiYWNrKFxuICAgICAgICBjYWxsYmFja0NvbnRleHQuc3RhdGUsXG4gICAgICAgIGF1dGhTdGF0ZUNvbnRyb2wsXG4gICAgICAgIGNvbmZpZ1xuICAgICAgKTtcblxuICAgIGlmICghaXNTdGF0ZUNvcnJlY3QpIHtcbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcignY29kZUZsb3dDb2RlUmVxdWVzdCBpbmNvcnJlY3Qgc3RhdGUnKSk7XG4gICAgfVxuXG4gICAgY29uc3QgYXV0aFdlbGxrbm93bkVuZHBvaW50cyA9IHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5yZWFkKFxuICAgICAgJ2F1dGhXZWxsS25vd25FbmRQb2ludHMnLFxuICAgICAgY29uZmlnXG4gICAgKTtcbiAgICBjb25zdCB0b2tlbkVuZHBvaW50ID0gYXV0aFdlbGxrbm93bkVuZHBvaW50cz8udG9rZW5FbmRwb2ludDtcblxuICAgIGlmICghdG9rZW5FbmRwb2ludCkge1xuICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IEVycm9yKCdUb2tlbiBFbmRwb2ludCBub3QgZGVmaW5lZCcpKTtcbiAgICB9XG5cbiAgICBsZXQgaGVhZGVyczogSHR0cEhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMoKTtcblxuICAgIGhlYWRlcnMgPSBoZWFkZXJzLnNldCgnQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpO1xuXG4gICAgY29uc3QgYm9keUZvckNvZGVGbG93ID0gdGhpcy51cmxTZXJ2aWNlLmNyZWF0ZUJvZHlGb3JDb2RlRmxvd0NvZGVSZXF1ZXN0KFxuICAgICAgY2FsbGJhY2tDb250ZXh0LmNvZGUsXG4gICAgICBjb25maWcsXG4gICAgICBjb25maWc/LmN1c3RvbVBhcmFtc0NvZGVSZXF1ZXN0XG4gICAgKTtcblxuICAgIHJldHVybiB0aGlzLmRhdGFTZXJ2aWNlXG4gICAgICAucG9zdCh0b2tlbkVuZHBvaW50LCBib2R5Rm9yQ29kZUZsb3csIGNvbmZpZywgaGVhZGVycylcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjb25zdCBhdXRoUmVzdWx0OiBBdXRoUmVzdWx0ID0ge1xuICAgICAgICAgICAgICAuLi5yZXNwb25zZSxcbiAgICAgICAgICAgICAgc3RhdGU6IGNhbGxiYWNrQ29udGV4dC5zdGF0ZSxcbiAgICAgICAgICAgICAgc2Vzc2lvbl9zdGF0ZTogY2FsbGJhY2tDb250ZXh0LnNlc3Npb25TdGF0ZSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNhbGxiYWNrQ29udGV4dC5hdXRoUmVzdWx0ID0gYXV0aFJlc3VsdDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gb2YoY2FsbGJhY2tDb250ZXh0KTtcbiAgICAgICAgfSksXG4gICAgICAgIHJldHJ5V2hlbigoZXJyb3IpID0+IHRoaXMuaGFuZGxlUmVmcmVzaFJldHJ5KGVycm9yLCBjb25maWcpKSxcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGF1dGhvcml0eSB9ID0gY29uZmlnO1xuICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBPaWRjU2VydmljZSBjb2RlIHJlcXVlc3QgJHthdXRob3JpdHl9YDtcblxuICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihjb25maWcsIGVycm9yTWVzc2FnZSwgZXJyb3IpO1xuXG4gICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IEVycm9yKGVycm9yTWVzc2FnZSkpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlUmVmcmVzaFJldHJ5KFxuICAgIGVycm9yczogT2JzZXJ2YWJsZTx1bmtub3duPixcbiAgICBjb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb25cbiAgKTogT2JzZXJ2YWJsZTx1bmtub3duPiB7XG4gICAgcmV0dXJuIGVycm9ycy5waXBlKFxuICAgICAgbWVyZ2VNYXAoKGVycm9yKSA9PiB7XG4gICAgICAgIC8vIHJldHJ5IHRva2VuIHJlZnJlc2ggaWYgdGhlcmUgaXMgbm8gaW50ZXJuZXQgY29ubmVjdGlvblxuICAgICAgICBpZiAoaXNOZXR3b3JrRXJyb3IoZXJyb3IpKSB7XG4gICAgICAgICAgY29uc3QgeyBhdXRob3JpdHksIHJlZnJlc2hUb2tlblJldHJ5SW5TZWNvbmRzIH0gPSBjb25maWc7XG4gICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYE9pZGNTZXJ2aWNlIGNvZGUgcmVxdWVzdCAke2F1dGhvcml0eX0gLSBubyBpbnRlcm5ldCBjb25uZWN0aW9uYDtcblxuICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dXYXJuaW5nKGNvbmZpZywgZXJyb3JNZXNzYWdlLCBlcnJvcik7XG5cbiAgICAgICAgICByZXR1cm4gdGltZXIoKHJlZnJlc2hUb2tlblJldHJ5SW5TZWNvbmRzID8/IDApICogMTAwMCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiJdfQ==