UNPKG

121 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License.
5 */
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.UserAgentApplication = void 0;
8var tslib_1 = require("tslib");
9var AccessTokenKey_1 = require("./cache/AccessTokenKey");
10var AccessTokenValue_1 = require("./cache/AccessTokenValue");
11var ServerRequestParameters_1 = require("./ServerRequestParameters");
12var Authority_1 = require("./authority/Authority");
13var ClientInfo_1 = require("./ClientInfo");
14var IdToken_1 = require("./IdToken");
15var AuthCache_1 = require("./cache/AuthCache");
16var Account_1 = require("./Account");
17var ScopeSet_1 = require("./ScopeSet");
18var StringUtils_1 = require("./utils/StringUtils");
19var WindowUtils_1 = require("./utils/WindowUtils");
20var TokenUtils_1 = require("./utils/TokenUtils");
21var TimeUtils_1 = require("./utils/TimeUtils");
22var UrlUtils_1 = require("./utils/UrlUtils");
23var RequestUtils_1 = require("./utils/RequestUtils");
24var ResponseUtils_1 = require("./utils/ResponseUtils");
25var AuthorityFactory_1 = require("./authority/AuthorityFactory");
26var Configuration_1 = require("./Configuration");
27var ClientConfigurationError_1 = require("./error/ClientConfigurationError");
28var AuthError_1 = require("./error/AuthError");
29var ClientAuthError_1 = require("./error/ClientAuthError");
30var ServerError_1 = require("./error/ServerError");
31var InteractionRequiredAuthError_1 = require("./error/InteractionRequiredAuthError");
32var AuthResponse_1 = require("./AuthResponse");
33var TelemetryManager_1 = tslib_1.__importDefault(require("./telemetry/TelemetryManager"));
34var ApiEvent_1 = require("./telemetry/ApiEvent");
35var Constants_1 = require("./utils/Constants");
36var CryptoUtils_1 = require("./utils/CryptoUtils");
37var TrustedAuthority_1 = require("./authority/TrustedAuthority");
38var AuthCacheUtils_1 = require("./utils/AuthCacheUtils");
39// default authority
40var DEFAULT_AUTHORITY = "https://login.microsoftonline.com/common";
41/**
42 * UserAgentApplication class
43 *
44 * Object Instance that the developer can use to make loginXX OR acquireTokenXX functions
45 */
46var UserAgentApplication = /** @class */ (function () {
47 /**
48 * @constructor
49 * Constructor for the UserAgentApplication used to instantiate the UserAgentApplication object
50 *
51 * Important attributes in the Configuration object for auth are:
52 * - clientID: the application ID of your application.
53 * You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview
54 * - authority: the authority URL for your application.
55 *
56 * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.
57 * It is of the form https://login.microsoftonline.com/<Enter_the_Tenant_Info_Here>.
58 * If your application supports Accounts in one organizational directory, replace "Enter_the_Tenant_Info_Here" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).
59 * If your application supports Accounts in any organizational directory, replace "Enter_the_Tenant_Info_Here" value with organizations.
60 * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace "Enter_the_Tenant_Info_Here" value with common.
61 * To restrict support to Personal Microsoft accounts only, replace "Enter_the_Tenant_Info_Here" value with consumers.
62 *
63 *
64 * In Azure B2C, authority is of the form https://<instance>/tfp/<tenant>/<policyName>/
65 *
66 * @param {@link (Configuration:type)} configuration object for the MSAL UserAgentApplication instance
67 */
68 function UserAgentApplication(configuration) {
69 // callbacks for token/error
70 this.authResponseCallback = null;
71 this.tokenReceivedCallback = null;
72 this.errorReceivedCallback = null;
73 // Set the Configuration
74 this.config = Configuration_1.buildConfiguration(configuration);
75 this.logger = this.config.system.logger;
76 this.clientId = this.config.auth.clientId;
77 this.inCookie = this.config.cache.storeAuthStateInCookie;
78 this.telemetryManager = this.getTelemetryManagerFromConfig(this.config.system.telemetry, this.clientId);
79 TrustedAuthority_1.TrustedAuthority.setTrustedAuthoritiesFromConfig(this.config.auth.validateAuthority, this.config.auth.knownAuthorities);
80 AuthorityFactory_1.AuthorityFactory.saveMetadataFromConfig(this.config.auth.authority, this.config.auth.authorityMetadata);
81 // if no authority is passed, set the default: "https://login.microsoftonline.com/common"
82 this.authority = this.config.auth.authority || DEFAULT_AUTHORITY;
83 // cache keys msal - typescript throws an error if any value other than "localStorage" or "sessionStorage" is passed
84 this.cacheStorage = new AuthCache_1.AuthCache(this.clientId, this.config.cache.cacheLocation, this.inCookie);
85 // Initialize window handling code
86 if (!window.activeRenewals) {
87 window.activeRenewals = {};
88 }
89 if (!window.renewStates) {
90 window.renewStates = [];
91 }
92 if (!window.callbackMappedToRenewStates) {
93 window.callbackMappedToRenewStates = {};
94 }
95 if (!window.promiseMappedToRenewStates) {
96 window.promiseMappedToRenewStates = {};
97 }
98 window.msal = this;
99 var urlHash = window.location.hash;
100 var urlContainsHash = UrlUtils_1.UrlUtils.urlContainsHash(urlHash);
101 // check if back button is pressed
102 WindowUtils_1.WindowUtils.checkIfBackButtonIsPressed(this.cacheStorage);
103 // On the server 302 - Redirect, handle this
104 if (urlContainsHash && this.cacheStorage.isInteractionInProgress(true)) {
105 var stateInfo = this.getResponseState(urlHash);
106 if (stateInfo.method === Constants_1.Constants.interactionTypeRedirect) {
107 this.handleRedirectAuthenticationResponse(urlHash);
108 }
109 }
110 }
111 Object.defineProperty(UserAgentApplication.prototype, "authority", {
112 /**
113 * Method to manage the authority URL.
114 *
115 * @returns {string} authority
116 */
117 get: function () {
118 return this.authorityInstance.CanonicalAuthority;
119 },
120 /**
121 * setter for the authority URL
122 * @param {string} authority
123 */
124 // If the developer passes an authority, create an instance
125 set: function (val) {
126 this.authorityInstance = AuthorityFactory_1.AuthorityFactory.CreateInstance(val, this.config.auth.validateAuthority);
127 },
128 enumerable: false,
129 configurable: true
130 });
131 /**
132 * Get the current authority instance from the MSAL configuration object
133 *
134 * @returns {@link Authority} authority instance
135 */
136 UserAgentApplication.prototype.getAuthorityInstance = function () {
137 return this.authorityInstance;
138 };
139 UserAgentApplication.prototype.handleRedirectCallback = function (authOrTokenCallback, errorReceivedCallback) {
140 if (!authOrTokenCallback) {
141 throw ClientConfigurationError_1.ClientConfigurationError.createInvalidCallbackObjectError(authOrTokenCallback);
142 }
143 // Set callbacks
144 if (errorReceivedCallback) {
145 this.tokenReceivedCallback = authOrTokenCallback;
146 this.errorReceivedCallback = errorReceivedCallback;
147 this.logger.warning("This overload for callback is deprecated - please change the format of the callbacks to a single callback as shown: (err: AuthError, response: AuthResponse).");
148 }
149 else {
150 this.authResponseCallback = authOrTokenCallback;
151 }
152 if (this.redirectError) {
153 this.authErrorHandler(Constants_1.Constants.interactionTypeRedirect, this.redirectError, this.redirectResponse);
154 }
155 else if (this.redirectResponse) {
156 this.authResponseHandler(Constants_1.Constants.interactionTypeRedirect, this.redirectResponse);
157 }
158 };
159 /**
160 * Public API to verify if the URL contains the hash with known properties
161 * @param hash
162 */
163 UserAgentApplication.prototype.urlContainsHash = function (hash) {
164 this.logger.verbose("UrlContainsHash has been called");
165 return UrlUtils_1.UrlUtils.urlContainsHash(hash);
166 };
167 UserAgentApplication.prototype.authResponseHandler = function (interactionType, response, resolve) {
168 this.logger.verbose("AuthResponseHandler has been called");
169 this.cacheStorage.setInteractionInProgress(false);
170 if (interactionType === Constants_1.Constants.interactionTypeRedirect) {
171 this.logger.verbose("Interaction type is redirect");
172 if (this.errorReceivedCallback) {
173 this.logger.verbose("Two callbacks were provided to handleRedirectCallback, calling success callback with response");
174 this.tokenReceivedCallback(response);
175 }
176 else if (this.authResponseCallback) {
177 this.logger.verbose("One callback was provided to handleRedirectCallback, calling authResponseCallback with response");
178 this.authResponseCallback(null, response);
179 }
180 }
181 else if (interactionType === Constants_1.Constants.interactionTypePopup) {
182 this.logger.verbose("Interaction type is popup, resolving");
183 resolve(response);
184 }
185 else {
186 throw ClientAuthError_1.ClientAuthError.createInvalidInteractionTypeError();
187 }
188 };
189 UserAgentApplication.prototype.authErrorHandler = function (interactionType, authErr, response, reject) {
190 this.logger.verbose("AuthErrorHandler has been called");
191 // set interaction_status to complete
192 this.cacheStorage.setInteractionInProgress(false);
193 if (interactionType === Constants_1.Constants.interactionTypeRedirect) {
194 this.logger.verbose("Interaction type is redirect");
195 if (this.errorReceivedCallback) {
196 this.logger.verbose("Two callbacks were provided to handleRedirectCallback, calling error callback");
197 this.errorReceivedCallback(authErr, response.accountState);
198 }
199 else if (this.authResponseCallback) {
200 this.logger.verbose("One callback was provided to handleRedirectCallback, calling authResponseCallback with error");
201 this.authResponseCallback(authErr, response);
202 }
203 else {
204 this.logger.verbose("handleRedirectCallback has not been called and no callbacks are registered, throwing error");
205 throw authErr;
206 }
207 }
208 else if (interactionType === Constants_1.Constants.interactionTypePopup) {
209 this.logger.verbose("Interaction type is popup, rejecting");
210 reject(authErr);
211 }
212 else {
213 throw ClientAuthError_1.ClientAuthError.createInvalidInteractionTypeError();
214 }
215 };
216 // #endregion
217 /**
218 * Use when initiating the login process by redirecting the user's browser to the authorization endpoint.
219 * @param {@link (AuthenticationParameters:type)}
220 */
221 UserAgentApplication.prototype.loginRedirect = function (userRequest) {
222 this.logger.verbose("LoginRedirect has been called");
223 // validate request
224 var request = RequestUtils_1.RequestUtils.validateRequest(userRequest, true, this.clientId, Constants_1.Constants.interactionTypeRedirect);
225 this.acquireTokenInteractive(Constants_1.Constants.interactionTypeRedirect, true, request, null, null);
226 };
227 /**
228 * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint.
229 * @param {@link (AuthenticationParameters:type)}
230 *
231 * To renew idToken, please pass clientId as the only scope in the Authentication Parameters
232 */
233 UserAgentApplication.prototype.acquireTokenRedirect = function (userRequest) {
234 this.logger.verbose("AcquireTokenRedirect has been called");
235 // validate request
236 var request = RequestUtils_1.RequestUtils.validateRequest(userRequest, false, this.clientId, Constants_1.Constants.interactionTypeRedirect);
237 this.acquireTokenInteractive(Constants_1.Constants.interactionTypeRedirect, false, request, null, null);
238 };
239 /**
240 * Use when initiating the login process via opening a popup window in the user's browser
241 *
242 * @param {@link (AuthenticationParameters:type)}
243 *
244 * @returns {Promise.<AuthResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
245 */
246 UserAgentApplication.prototype.loginPopup = function (userRequest) {
247 var _this = this;
248 this.logger.verbose("LoginPopup has been called");
249 // validate request
250 var request = RequestUtils_1.RequestUtils.validateRequest(userRequest, true, this.clientId, Constants_1.Constants.interactionTypePopup);
251 var apiEvent = this.telemetryManager.createAndStartApiEvent(request.correlationId, ApiEvent_1.API_EVENT_IDENTIFIER.LoginPopup);
252 return new Promise(function (resolve, reject) {
253 _this.acquireTokenInteractive(Constants_1.Constants.interactionTypePopup, true, request, resolve, reject);
254 })
255 .then(function (resp) {
256 _this.logger.verbose("Successfully logged in");
257 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, true);
258 return resp;
259 })
260 .catch(function (error) {
261 _this.cacheStorage.resetTempCacheItems(request.state);
262 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, false, error.errorCode);
263 throw error;
264 });
265 };
266 /**
267 * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser
268 * @param {@link AuthenticationParameters}
269 *
270 * To renew idToken, please pass clientId as the only scope in the Authentication Parameters
271 * @returns {Promise.<AuthResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
272 */
273 UserAgentApplication.prototype.acquireTokenPopup = function (userRequest) {
274 var _this = this;
275 this.logger.verbose("AcquireTokenPopup has been called");
276 // validate request
277 var request = RequestUtils_1.RequestUtils.validateRequest(userRequest, false, this.clientId, Constants_1.Constants.interactionTypePopup);
278 var apiEvent = this.telemetryManager.createAndStartApiEvent(request.correlationId, ApiEvent_1.API_EVENT_IDENTIFIER.AcquireTokenPopup);
279 return new Promise(function (resolve, reject) {
280 _this.acquireTokenInteractive(Constants_1.Constants.interactionTypePopup, false, request, resolve, reject);
281 })
282 .then(function (resp) {
283 _this.logger.verbose("Successfully acquired token");
284 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, true);
285 return resp;
286 })
287 .catch(function (error) {
288 _this.cacheStorage.resetTempCacheItems(request.state);
289 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, false, error.errorCode);
290 throw error;
291 });
292 };
293 // #region Acquire Token
294 /**
295 * Use when initiating the login process or when you want to obtain an access_token for your API,
296 * either by redirecting the user's browser window to the authorization endpoint or via opening a popup window in the user's browser.
297 * @param {@link (AuthenticationParameters:type)}
298 *
299 * To renew idToken, please pass clientId as the only scope in the Authentication Parameters
300 */
301 UserAgentApplication.prototype.acquireTokenInteractive = function (interactionType, isLoginCall, request, resolve, reject) {
302 var _this = this;
303 this.logger.verbose("AcquireTokenInteractive has been called");
304 // block the request if made from the hidden iframe
305 WindowUtils_1.WindowUtils.blockReloadInHiddenIframes();
306 try {
307 this.cacheStorage.setInteractionInProgress(true);
308 }
309 catch (e) {
310 // If already in progress, do not proceed
311 var thrownError = isLoginCall ? ClientAuthError_1.ClientAuthError.createLoginInProgressError() : ClientAuthError_1.ClientAuthError.createAcquireTokenInProgressError();
312 var stateOnlyResponse = AuthResponse_1.buildResponseStateOnly(this.getAccountState(request.state));
313 this.cacheStorage.resetTempCacheItems(request.state);
314 this.authErrorHandler(interactionType, thrownError, stateOnlyResponse, reject);
315 return;
316 }
317 if (interactionType === Constants_1.Constants.interactionTypeRedirect) {
318 this.cacheStorage.setItem(Constants_1.TemporaryCacheKeys.REDIRECT_REQUEST, "" + Constants_1.Constants.inProgress + Constants_1.Constants.resourceDelimiter + request.state);
319 }
320 // Get the account object if a session exists
321 var account;
322 if (request && request.account && !isLoginCall) {
323 account = request.account;
324 this.logger.verbose("Account set from request");
325 }
326 else {
327 account = this.getAccount();
328 this.logger.verbose("Account set from MSAL Cache");
329 }
330 // If no session exists, prompt the user to login.
331 if (!account && !ServerRequestParameters_1.ServerRequestParameters.isSSOParam(request)) {
332 if (isLoginCall) {
333 // extract ADAL id_token if exists
334 var adalIdToken = this.extractADALIdToken();
335 // silent login if ADAL id_token is retrieved successfully - SSO
336 if (adalIdToken && !request.scopes) {
337 this.logger.info("ADAL's idToken exists. Extracting login information from ADAL's idToken");
338 var tokenRequest = this.buildIDTokenRequest(request);
339 this.silentLogin = true;
340 this.acquireTokenSilent(tokenRequest).then(function (response) {
341 _this.silentLogin = false;
342 _this.logger.info("Unified cache call is successful");
343 _this.authResponseHandler(interactionType, response, resolve);
344 return;
345 }, function (error) {
346 _this.silentLogin = false;
347 _this.logger.error("Error occurred during unified cache ATS: " + error);
348 // proceed to login since ATS failed
349 _this.acquireTokenHelper(null, interactionType, isLoginCall, request, resolve, reject);
350 });
351 }
352 // No ADAL token found, proceed to login
353 else {
354 this.logger.verbose("Login call but no token found, proceed to login");
355 this.acquireTokenHelper(null, interactionType, isLoginCall, request, resolve, reject);
356 }
357 }
358 // AcquireToken call, but no account or context given, so throw error
359 else {
360 this.logger.verbose("AcquireToken call, no context or account given");
361 this.logger.info("User login is required");
362 var stateOnlyResponse = AuthResponse_1.buildResponseStateOnly(this.getAccountState(request.state));
363 this.cacheStorage.resetTempCacheItems(request.state);
364 this.authErrorHandler(interactionType, ClientAuthError_1.ClientAuthError.createUserLoginRequiredError(), stateOnlyResponse, reject);
365 return;
366 }
367 }
368 // User session exists
369 else {
370 this.logger.verbose("User session exists, login not required");
371 this.acquireTokenHelper(account, interactionType, isLoginCall, request, resolve, reject);
372 }
373 };
374 /**
375 * @hidden
376 * @ignore
377 * Helper function to acquireToken
378 *
379 */
380 UserAgentApplication.prototype.acquireTokenHelper = function (account, interactionType, isLoginCall, request, resolve, reject) {
381 return tslib_1.__awaiter(this, void 0, void 0, function () {
382 var requestSignature, serverAuthenticationRequest, acquireTokenAuthority, popUpWindow, responseType, loginStartPage, urlNavigate, hash, error_1, navigate, err_1;
383 return tslib_1.__generator(this, function (_a) {
384 switch (_a.label) {
385 case 0:
386 this.logger.verbose("AcquireTokenHelper has been called");
387 this.logger.verbose("Interaction type: " + interactionType + ". isLoginCall: " + isLoginCall);
388 requestSignature = request.scopes ? request.scopes.join(" ").toLowerCase() : Constants_1.Constants.oidcScopes.join(" ");
389 this.logger.verbosePii("Request signature: " + requestSignature);
390 acquireTokenAuthority = (request && request.authority) ? AuthorityFactory_1.AuthorityFactory.CreateInstance(request.authority, this.config.auth.validateAuthority, request.authorityMetadata) : this.authorityInstance;
391 _a.label = 1;
392 case 1:
393 _a.trys.push([1, 11, , 12]);
394 if (!!acquireTokenAuthority.hasCachedMetadata()) return [3 /*break*/, 3];
395 this.logger.verbose("No cached metadata for authority");
396 return [4 /*yield*/, AuthorityFactory_1.AuthorityFactory.saveMetadataFromNetwork(acquireTokenAuthority, this.telemetryManager, request.correlationId)];
397 case 2:
398 _a.sent();
399 return [3 /*break*/, 4];
400 case 3:
401 this.logger.verbose("Cached metadata found for authority");
402 _a.label = 4;
403 case 4:
404 responseType = isLoginCall ? Constants_1.ResponseTypes.id_token : this.getTokenType(account, request.scopes);
405 loginStartPage = request.redirectStartPage || window.location.href;
406 serverAuthenticationRequest = new ServerRequestParameters_1.ServerRequestParameters(acquireTokenAuthority, this.clientId, responseType, this.getRedirectUri(request && request.redirectUri), request.scopes, request.state, request.correlationId);
407 this.logger.verbose("Finished building server authentication request");
408 this.updateCacheEntries(serverAuthenticationRequest, account, isLoginCall, loginStartPage);
409 this.logger.verbose("Updating cache entries");
410 // populate QueryParameters (sid/login_hint) and any other extraQueryParameters set by the developer
411 serverAuthenticationRequest.populateQueryParams(account, request);
412 this.logger.verbose("Query parameters populated from account");
413 urlNavigate = UrlUtils_1.UrlUtils.createNavigateUrl(serverAuthenticationRequest) + Constants_1.Constants.response_mode_fragment;
414 // set state in cache
415 if (interactionType === Constants_1.Constants.interactionTypeRedirect) {
416 if (!isLoginCall) {
417 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.STATE_ACQ_TOKEN, request.state), serverAuthenticationRequest.state, this.inCookie);
418 this.logger.verbose("State cached for redirect");
419 this.logger.verbosePii("State cached: " + serverAuthenticationRequest.state);
420 }
421 else {
422 this.logger.verbose("Interaction type redirect but login call is true. State not cached");
423 }
424 }
425 else if (interactionType === Constants_1.Constants.interactionTypePopup) {
426 window.renewStates.push(serverAuthenticationRequest.state);
427 window.requestType = isLoginCall ? Constants_1.Constants.login : Constants_1.Constants.renewToken;
428 this.logger.verbose("State saved to window");
429 this.logger.verbosePii("State saved: " + serverAuthenticationRequest.state);
430 // Register callback to capture results from server
431 this.registerCallback(serverAuthenticationRequest.state, requestSignature, resolve, reject);
432 }
433 else {
434 this.logger.verbose("Invalid interaction error. State not cached");
435 throw ClientAuthError_1.ClientAuthError.createInvalidInteractionTypeError();
436 }
437 if (!(interactionType === Constants_1.Constants.interactionTypePopup)) return [3 /*break*/, 9];
438 this.logger.verbose("Interaction type is popup. Generating popup window");
439 // Generate a popup window
440 try {
441 popUpWindow = this.openPopup(urlNavigate, "msal", Constants_1.Constants.popUpWidth, Constants_1.Constants.popUpHeight);
442 // Push popup window handle onto stack for tracking
443 WindowUtils_1.WindowUtils.trackPopup(popUpWindow);
444 }
445 catch (e) {
446 this.logger.info(ClientAuthError_1.ClientAuthErrorMessage.popUpWindowError.code + ":" + ClientAuthError_1.ClientAuthErrorMessage.popUpWindowError.desc);
447 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR, ClientAuthError_1.ClientAuthErrorMessage.popUpWindowError.code);
448 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR_DESC, ClientAuthError_1.ClientAuthErrorMessage.popUpWindowError.desc);
449 if (reject) {
450 reject(ClientAuthError_1.ClientAuthError.createPopupWindowError());
451 return [2 /*return*/];
452 }
453 }
454 if (!popUpWindow) return [3 /*break*/, 8];
455 _a.label = 5;
456 case 5:
457 _a.trys.push([5, 7, , 8]);
458 return [4 /*yield*/, WindowUtils_1.WindowUtils.monitorPopupForHash(popUpWindow, this.config.system.loadFrameTimeout, urlNavigate, this.logger)];
459 case 6:
460 hash = _a.sent();
461 this.handleAuthenticationResponse(hash);
462 // Request completed successfully, set to completed
463 this.cacheStorage.setInteractionInProgress(false);
464 this.logger.info("Closing popup window");
465 // TODO: Check how this can be extracted for any framework specific code?
466 if (this.config.framework.isAngular) {
467 this.broadcast("msal:popUpHashChanged", hash);
468 }
469 WindowUtils_1.WindowUtils.closePopups();
470 return [3 /*break*/, 8];
471 case 7:
472 error_1 = _a.sent();
473 if (reject) {
474 reject(error_1);
475 }
476 if (this.config.framework.isAngular) {
477 this.broadcast("msal:popUpClosed", error_1.errorCode + Constants_1.Constants.resourceDelimiter + error_1.errorMessage);
478 }
479 else {
480 // Request failed, set to canceled
481 this.cacheStorage.setInteractionInProgress(false);
482 popUpWindow.close();
483 }
484 return [3 /*break*/, 8];
485 case 8: return [3 /*break*/, 10];
486 case 9:
487 // If onRedirectNavigate is implemented, invoke it and provide urlNavigate
488 if (request.onRedirectNavigate) {
489 this.logger.verbose("Invoking onRedirectNavigate callback");
490 navigate = request.onRedirectNavigate(urlNavigate);
491 // Returning false from onRedirectNavigate will stop navigation
492 if (navigate !== false) {
493 this.logger.verbose("onRedirectNavigate did not return false, navigating");
494 this.navigateWindow(urlNavigate);
495 }
496 else {
497 this.logger.verbose("onRedirectNavigate returned false, stopping navigation");
498 }
499 }
500 else {
501 // Otherwise, perform navigation
502 this.logger.verbose("Navigating window to urlNavigate");
503 this.navigateWindow(urlNavigate);
504 }
505 _a.label = 10;
506 case 10: return [3 /*break*/, 12];
507 case 11:
508 err_1 = _a.sent();
509 this.logger.error(err_1);
510 this.cacheStorage.resetTempCacheItems(request.state);
511 this.authErrorHandler(interactionType, ClientAuthError_1.ClientAuthError.createEndpointResolutionError(err_1.toString), AuthResponse_1.buildResponseStateOnly(request.state), reject);
512 if (popUpWindow) {
513 popUpWindow.close();
514 }
515 return [3 /*break*/, 12];
516 case 12: return [2 /*return*/];
517 }
518 });
519 });
520 };
521 /**
522 * API interfacing idToken request when applications already have a session/hint acquired by authorization client applications
523 * @param request
524 */
525 UserAgentApplication.prototype.ssoSilent = function (request) {
526 this.logger.verbose("ssoSilent has been called");
527 // throw an error on an empty request
528 if (!request) {
529 throw ClientConfigurationError_1.ClientConfigurationError.createEmptyRequestError();
530 }
531 // throw an error on no hints passed
532 if (!request.sid && !request.loginHint) {
533 throw ClientConfigurationError_1.ClientConfigurationError.createSsoSilentError();
534 }
535 return this.acquireTokenSilent(tslib_1.__assign(tslib_1.__assign({}, request), { scopes: Constants_1.Constants.oidcScopes }));
536 };
537 /**
538 * Use this function to obtain a token before every call to the API / resource provider
539 *
540 * MSAL return's a cached token when available
541 * Or it send's a request to the STS to obtain a new token using a hidden iframe.
542 *
543 * @param {@link AuthenticationParameters}
544 *
545 * To renew idToken, please pass clientId as the only scope in the Authentication Parameters
546 * @returns {Promise.<AuthResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
547 *
548 */
549 UserAgentApplication.prototype.acquireTokenSilent = function (userRequest) {
550 var _this = this;
551 this.logger.verbose("AcquireTokenSilent has been called");
552 // validate the request
553 var request = RequestUtils_1.RequestUtils.validateRequest(userRequest, false, this.clientId, Constants_1.Constants.interactionTypeSilent);
554 var apiEvent = this.telemetryManager.createAndStartApiEvent(request.correlationId, ApiEvent_1.API_EVENT_IDENTIFIER.AcquireTokenSilent);
555 var requestSignature = RequestUtils_1.RequestUtils.createRequestSignature(request);
556 return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
557 var scope, account, adalIdToken, responseType, serverAuthenticationRequest, adalIdTokenObject, userContainedClaims, authErr, cacheResultResponse, logMessage, err_2;
558 return tslib_1.__generator(this, function (_a) {
559 switch (_a.label) {
560 case 0:
561 // block the request if made from the hidden iframe
562 WindowUtils_1.WindowUtils.blockReloadInHiddenIframes();
563 scope = request.scopes.join(" ").toLowerCase();
564 this.logger.verbosePii("Serialized scopes: " + scope);
565 if (request.account) {
566 account = request.account;
567 this.logger.verbose("Account set from request");
568 }
569 else {
570 account = this.getAccount();
571 this.logger.verbose("Account set from MSAL Cache");
572 }
573 adalIdToken = this.cacheStorage.getItem(Constants_1.Constants.adalIdToken);
574 // In the event of no account being passed in the config, no session id, and no pre-existing adalIdToken, user will need to log in
575 if (!account && !(request.sid || request.loginHint) && StringUtils_1.StringUtils.isEmpty(adalIdToken)) {
576 this.logger.info("User login is required");
577 // The promise rejects with a UserLoginRequiredError, which should be caught and user should be prompted to log in interactively
578 return [2 /*return*/, reject(ClientAuthError_1.ClientAuthError.createUserLoginRequiredError())];
579 }
580 responseType = this.getTokenType(account, request.scopes);
581 this.logger.verbose("Response type: " + responseType);
582 serverAuthenticationRequest = new ServerRequestParameters_1.ServerRequestParameters(AuthorityFactory_1.AuthorityFactory.CreateInstance(request.authority, this.config.auth.validateAuthority, request.authorityMetadata), this.clientId, responseType, this.getRedirectUri(request.redirectUri), request.scopes, request.state, request.correlationId);
583 this.logger.verbose("Finished building server authentication request");
584 // populate QueryParameters (sid/login_hint) and any other extraQueryParameters set by the developer
585 if (ServerRequestParameters_1.ServerRequestParameters.isSSOParam(request) || account) {
586 serverAuthenticationRequest.populateQueryParams(account, request, null, true);
587 this.logger.verbose("Query parameters populated from existing SSO or account");
588 }
589 // if user didn't pass login_hint/sid and adal's idtoken is present, extract the login_hint from the adalIdToken
590 else if (!account && !StringUtils_1.StringUtils.isEmpty(adalIdToken)) {
591 adalIdTokenObject = TokenUtils_1.TokenUtils.extractIdToken(adalIdToken);
592 this.logger.verbose("ADAL's idToken exists. Extracting login information from ADAL's idToken to populate query parameters");
593 serverAuthenticationRequest.populateQueryParams(account, null, adalIdTokenObject, true);
594 }
595 else {
596 this.logger.verbose("No additional query parameters added");
597 }
598 userContainedClaims = request.claimsRequest || serverAuthenticationRequest.claimsValue;
599 // If request.forceRefresh is set to true, force a request for a new token instead of getting it from the cache
600 if (!userContainedClaims && !request.forceRefresh) {
601 try {
602 cacheResultResponse = this.getCachedToken(serverAuthenticationRequest, account);
603 }
604 catch (e) {
605 authErr = e;
606 }
607 }
608 if (!cacheResultResponse) return [3 /*break*/, 1];
609 this.logger.verbose("Token found in cache lookup");
610 this.logger.verbosePii("Scopes found: " + JSON.stringify(cacheResultResponse.scopes));
611 resolve(cacheResultResponse);
612 return [2 /*return*/, null];
613 case 1:
614 if (!authErr) return [3 /*break*/, 2];
615 this.logger.infoPii(authErr.errorCode + ":" + authErr.errorMessage);
616 reject(authErr);
617 return [2 /*return*/, null];
618 case 2:
619 logMessage = void 0;
620 if (userContainedClaims) {
621 logMessage = "Skipped cache lookup since claims were given";
622 }
623 else if (request.forceRefresh) {
624 logMessage = "Skipped cache lookup since request.forceRefresh option was set to true";
625 }
626 else {
627 logMessage = "No valid token found in cache lookup";
628 }
629 this.logger.verbose(logMessage);
630 // Cache result can return null if cache is empty. In that case, set authority to default value if no authority is passed to the API.
631 if (!serverAuthenticationRequest.authorityInstance) {
632 serverAuthenticationRequest.authorityInstance = request.authority ?
633 AuthorityFactory_1.AuthorityFactory.CreateInstance(request.authority, this.config.auth.validateAuthority, request.authorityMetadata)
634 : this.authorityInstance;
635 }
636 this.logger.verbosePii("Authority instance: " + serverAuthenticationRequest.authority);
637 _a.label = 3;
638 case 3:
639 _a.trys.push([3, 7, , 8]);
640 if (!!serverAuthenticationRequest.authorityInstance.hasCachedMetadata()) return [3 /*break*/, 5];
641 this.logger.verbose("No cached metadata for authority");
642 return [4 /*yield*/, AuthorityFactory_1.AuthorityFactory.saveMetadataFromNetwork(serverAuthenticationRequest.authorityInstance, this.telemetryManager, request.correlationId)];
643 case 4:
644 _a.sent();
645 this.logger.verbose("Authority has been updated with endpoint discovery response");
646 return [3 /*break*/, 6];
647 case 5:
648 this.logger.verbose("Cached metadata found for authority");
649 _a.label = 6;
650 case 6:
651 /*
652 * refresh attempt with iframe
653 * Already renewing for this scope, callback when we get the token.
654 */
655 if (window.activeRenewals[requestSignature]) {
656 this.logger.verbose("Renewing token in progress. Registering callback");
657 // Active renewals contains the state for each renewal.
658 this.registerCallback(window.activeRenewals[requestSignature], requestSignature, resolve, reject);
659 }
660 else {
661 if (request.scopes && ScopeSet_1.ScopeSet.onlyContainsOidcScopes(request.scopes)) {
662 /*
663 * App uses idToken to send to api endpoints
664 * Default scope is tracked as OIDC scopes to store this token
665 */
666 this.logger.verbose("OpenID Connect scopes only, renewing idToken");
667 this.silentLogin = true;
668 this.renewIdToken(requestSignature, resolve, reject, account, serverAuthenticationRequest);
669 }
670 else {
671 // renew access token
672 this.logger.verbose("Renewing access token");
673 this.renewToken(requestSignature, resolve, reject, account, serverAuthenticationRequest);
674 }
675 }
676 return [3 /*break*/, 8];
677 case 7:
678 err_2 = _a.sent();
679 this.logger.error(err_2);
680 reject(ClientAuthError_1.ClientAuthError.createEndpointResolutionError(err_2.toString()));
681 return [2 /*return*/, null];
682 case 8: return [2 /*return*/];
683 }
684 });
685 }); })
686 .then(function (res) {
687 _this.logger.verbose("Successfully acquired token");
688 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, true);
689 return res;
690 })
691 .catch(function (error) {
692 _this.cacheStorage.resetTempCacheItems(request.state);
693 _this.telemetryManager.stopAndFlushApiEvent(request.correlationId, apiEvent, false, error.errorCode);
694 throw error;
695 });
696 };
697 // #endregion
698 // #region Popup Window Creation
699 /**
700 * @hidden
701 *
702 * Configures popup window for login.
703 *
704 * @param urlNavigate
705 * @param title
706 * @param popUpWidth
707 * @param popUpHeight
708 * @ignore
709 * @hidden
710 */
711 UserAgentApplication.prototype.openPopup = function (urlNavigate, title, popUpWidth, popUpHeight) {
712 this.logger.verbose("OpenPopup has been called");
713 try {
714 /**
715 * adding winLeft and winTop to account for dual monitor
716 * using screenLeft and screenTop for IE8 and earlier
717 */
718 var winLeft = window.screenLeft ? window.screenLeft : window.screenX;
719 var winTop = window.screenTop ? window.screenTop : window.screenY;
720 /**
721 * window.innerWidth displays browser window"s height and width excluding toolbars
722 * using document.documentElement.clientWidth for IE8 and earlier
723 */
724 var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
725 var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
726 var left = ((width / 2) - (popUpWidth / 2)) + winLeft;
727 var top_1 = ((height / 2) - (popUpHeight / 2)) + winTop;
728 // open the window
729 var popupWindow = window.open(urlNavigate, title, "width=" + popUpWidth + ", height=" + popUpHeight + ", top=" + top_1 + ", left=" + left + ", scrollbars=yes");
730 if (!popupWindow) {
731 throw ClientAuthError_1.ClientAuthError.createPopupWindowError();
732 }
733 if (popupWindow.focus) {
734 popupWindow.focus();
735 }
736 return popupWindow;
737 }
738 catch (e) {
739 this.cacheStorage.setInteractionInProgress(false);
740 throw ClientAuthError_1.ClientAuthError.createPopupWindowError(e.toString());
741 }
742 };
743 // #endregion
744 // #region Iframe Management
745 /**
746 * @hidden
747 * Calling _loadFrame but with a timeout to signal failure in loadframeStatus. Callbacks are left.
748 * registered when network errors occur and subsequent token requests for same resource are registered to the pending request.
749 * @ignore
750 */
751 UserAgentApplication.prototype.loadIframeTimeout = function (urlNavigate, frameName, requestSignature) {
752 return tslib_1.__awaiter(this, void 0, void 0, function () {
753 var expectedState, iframe, _a, hash, error_2;
754 return tslib_1.__generator(this, function (_b) {
755 switch (_b.label) {
756 case 0:
757 expectedState = window.activeRenewals[requestSignature];
758 this.logger.verbosePii("Set loading state to pending for: " + requestSignature + ":" + expectedState);
759 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.RENEW_STATUS, expectedState), Constants_1.Constants.inProgress);
760 if (!this.config.system.navigateFrameWait) return [3 /*break*/, 2];
761 return [4 /*yield*/, WindowUtils_1.WindowUtils.loadFrame(urlNavigate, frameName, this.config.system.navigateFrameWait, this.logger)];
762 case 1:
763 _a = _b.sent();
764 return [3 /*break*/, 3];
765 case 2:
766 _a = WindowUtils_1.WindowUtils.loadFrameSync(urlNavigate, frameName, this.logger);
767 _b.label = 3;
768 case 3:
769 iframe = _a;
770 _b.label = 4;
771 case 4:
772 _b.trys.push([4, 6, , 7]);
773 return [4 /*yield*/, WindowUtils_1.WindowUtils.monitorIframeForHash(iframe.contentWindow, this.config.system.loadFrameTimeout, urlNavigate, this.logger)];
774 case 5:
775 hash = _b.sent();
776 if (hash) {
777 this.handleAuthenticationResponse(hash);
778 }
779 return [3 /*break*/, 7];
780 case 6:
781 error_2 = _b.sent();
782 if (this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.RENEW_STATUS, expectedState)) === Constants_1.Constants.inProgress) {
783 // fail the iframe session if it's in pending state
784 this.logger.verbose("Loading frame has timed out after: " + (this.config.system.loadFrameTimeout / 1000) + " seconds for scope/authority " + requestSignature + ":" + expectedState);
785 // Error after timeout
786 if (expectedState && window.callbackMappedToRenewStates[expectedState]) {
787 window.callbackMappedToRenewStates[expectedState](null, error_2);
788 }
789 this.cacheStorage.removeItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.RENEW_STATUS, expectedState));
790 }
791 WindowUtils_1.WindowUtils.removeHiddenIframe(iframe);
792 throw error_2;
793 case 7:
794 WindowUtils_1.WindowUtils.removeHiddenIframe(iframe);
795 return [2 /*return*/];
796 }
797 });
798 });
799 };
800 // #endregion
801 // #region General Helpers
802 /**
803 * @hidden
804 * Used to redirect the browser to the STS authorization endpoint
805 * @param {string} urlNavigate - URL of the authorization endpoint
806 */
807 UserAgentApplication.prototype.navigateWindow = function (urlNavigate, popupWindow) {
808 // Navigate if valid URL
809 if (urlNavigate && !StringUtils_1.StringUtils.isEmpty(urlNavigate)) {
810 var navigateWindow = popupWindow ? popupWindow : window;
811 var logMessage = popupWindow ? "Navigated Popup window to:" + urlNavigate : "Navigate to:" + urlNavigate;
812 this.logger.infoPii(logMessage);
813 navigateWindow.location.assign(urlNavigate);
814 }
815 else {
816 this.logger.info("Navigate url is empty");
817 throw AuthError_1.AuthError.createUnexpectedError("Navigate url is empty");
818 }
819 };
820 /**
821 * @hidden
822 * Used to add the developer requested callback to the array of callbacks for the specified scopes. The updated array is stored on the window object
823 * @param {string} expectedState - Unique state identifier (guid).
824 * @param {string} scope - Developer requested permissions. Not all scopes are guaranteed to be included in the access token returned.
825 * @param {Function} resolve - The resolve function of the promise object.
826 * @param {Function} reject - The reject function of the promise object.
827 * @ignore
828 */
829 UserAgentApplication.prototype.registerCallback = function (expectedState, requestSignature, resolve, reject) {
830 var _this = this;
831 // track active renewals
832 window.activeRenewals[requestSignature] = expectedState;
833 // initialize callbacks mapped array
834 if (!window.promiseMappedToRenewStates[expectedState]) {
835 window.promiseMappedToRenewStates[expectedState] = [];
836 }
837 // indexing on the current state, push the callback params to callbacks mapped
838 window.promiseMappedToRenewStates[expectedState].push({ resolve: resolve, reject: reject });
839 // Store the server response in the current window??
840 if (!window.callbackMappedToRenewStates[expectedState]) {
841 window.callbackMappedToRenewStates[expectedState] = function (response, error) {
842 // reset active renewals
843 delete window.activeRenewals[requestSignature];
844 // for all promiseMappedtoRenewStates for a given 'state' - call the reject/resolve with error/token respectively
845 for (var i = 0; i < window.promiseMappedToRenewStates[expectedState].length; ++i) {
846 try {
847 if (error) {
848 window.promiseMappedToRenewStates[expectedState][i].reject(error);
849 }
850 else if (response) {
851 window.promiseMappedToRenewStates[expectedState][i].resolve(response);
852 }
853 else {
854 _this.cacheStorage.resetTempCacheItems(expectedState);
855 throw AuthError_1.AuthError.createUnexpectedError("Error and response are both null");
856 }
857 }
858 catch (e) {
859 _this.logger.warning(e);
860 }
861 }
862 // reset
863 delete window.promiseMappedToRenewStates[expectedState];
864 delete window.callbackMappedToRenewStates[expectedState];
865 };
866 }
867 };
868 // #endregion
869 // #region Logout
870 /**
871 * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
872 * Default behaviour is to redirect the user to `window.location.href`.
873 */
874 UserAgentApplication.prototype.logout = function (correlationId) {
875 this.logger.verbose("Logout has been called");
876 this.logoutAsync(correlationId);
877 };
878 /**
879 * Async version of logout(). Use to log out the current user.
880 * @param correlationId Request correlationId
881 */
882 UserAgentApplication.prototype.logoutAsync = function (correlationId) {
883 return tslib_1.__awaiter(this, void 0, void 0, function () {
884 var requestCorrelationId, apiEvent, correlationIdParam, postLogoutQueryParam, urlNavigate, error_3;
885 return tslib_1.__generator(this, function (_a) {
886 switch (_a.label) {
887 case 0:
888 requestCorrelationId = correlationId || CryptoUtils_1.CryptoUtils.createNewGuid();
889 apiEvent = this.telemetryManager.createAndStartApiEvent(requestCorrelationId, ApiEvent_1.API_EVENT_IDENTIFIER.Logout);
890 this.clearCache();
891 this.account = null;
892 _a.label = 1;
893 case 1:
894 _a.trys.push([1, 5, , 6]);
895 if (!!this.authorityInstance.hasCachedMetadata()) return [3 /*break*/, 3];
896 this.logger.verbose("No cached metadata for authority");
897 return [4 /*yield*/, AuthorityFactory_1.AuthorityFactory.saveMetadataFromNetwork(this.authorityInstance, this.telemetryManager, correlationId)];
898 case 2:
899 _a.sent();
900 return [3 /*break*/, 4];
901 case 3:
902 this.logger.verbose("Cached metadata found for authority");
903 _a.label = 4;
904 case 4:
905 correlationIdParam = "client-request-id=" + requestCorrelationId;
906 postLogoutQueryParam = void 0;
907 if (this.getPostLogoutRedirectUri()) {
908 postLogoutQueryParam = "&post_logout_redirect_uri=" + encodeURIComponent(this.getPostLogoutRedirectUri());
909 this.logger.verbose("redirectUri found and set");
910 }
911 else {
912 postLogoutQueryParam = "";
913 this.logger.verbose("No redirectUri set for app. postLogoutQueryParam is empty");
914 }
915 urlNavigate = void 0;
916 if (this.authorityInstance.EndSessionEndpoint) {
917 urlNavigate = this.authorityInstance.EndSessionEndpoint + "?" + correlationIdParam + postLogoutQueryParam;
918 this.logger.verbose("EndSessionEndpoint found and urlNavigate set");
919 this.logger.verbosePii("urlNavigate set to: " + this.authorityInstance.EndSessionEndpoint);
920 }
921 else {
922 urlNavigate = this.authority + "oauth2/v2.0/logout?" + correlationIdParam + postLogoutQueryParam;
923 this.logger.verbose("No endpoint, urlNavigate set to default");
924 }
925 this.telemetryManager.stopAndFlushApiEvent(requestCorrelationId, apiEvent, true);
926 this.logger.verbose("Navigating window to urlNavigate");
927 this.navigateWindow(urlNavigate);
928 return [3 /*break*/, 6];
929 case 5:
930 error_3 = _a.sent();
931 this.telemetryManager.stopAndFlushApiEvent(requestCorrelationId, apiEvent, false, error_3.errorCode);
932 return [3 /*break*/, 6];
933 case 6: return [2 /*return*/];
934 }
935 });
936 });
937 };
938 /**
939 * @hidden
940 * Clear all access tokens and ID tokens in the cache.
941 * @ignore
942 */
943 UserAgentApplication.prototype.clearCache = function () {
944 this.logger.verbose("Clearing cache");
945 window.renewStates = [];
946 var tokenCacheItems = this.cacheStorage.getAllTokens(Constants_1.Constants.clientId, Constants_1.Constants.homeAccountIdentifier);
947 for (var i = 0; i < tokenCacheItems.length; i++) {
948 this.cacheStorage.removeItem(JSON.stringify(tokenCacheItems[i].key));
949 }
950 this.cacheStorage.resetCacheItems();
951 this.cacheStorage.clearMsalCookie();
952 this.logger.verbose("Cache cleared");
953 };
954 /**
955 * @hidden
956 * Clear a given access token from the cache.
957 *
958 * @param accessToken
959 */
960 UserAgentApplication.prototype.clearCacheForScope = function (accessToken) {
961 this.logger.verbose("Clearing access token from cache");
962 var accessTokenItems = this.cacheStorage.getAllAccessTokens(Constants_1.Constants.clientId, Constants_1.Constants.homeAccountIdentifier);
963 for (var i = 0; i < accessTokenItems.length; i++) {
964 var token = accessTokenItems[i];
965 if (token.value.accessToken === accessToken) {
966 this.cacheStorage.removeItem(JSON.stringify(token.key));
967 this.logger.verbosePii("Access token removed: " + token.key);
968 }
969 }
970 };
971 // #endregion
972 // #region Response
973 /**
974 * @hidden
975 * @ignore
976 * Checks if the redirect response is received from the STS. In case of redirect, the url fragment has either id_token, access_token or error.
977 * @param {string} hash - Hash passed from redirect page.
978 * @returns {Boolean} - true if response contains id_token, access_token or error, false otherwise.
979 */
980 UserAgentApplication.prototype.isCallback = function (hash) {
981 this.logger.info("isCallback will be deprecated in favor of urlContainsHash in MSAL.js v2.0.");
982 this.logger.verbose("isCallback has been called");
983 return UrlUtils_1.UrlUtils.urlContainsHash(hash);
984 };
985 /**
986 * @hidden
987 * Used to call the constructor callback with the token/error
988 * @param {string} [hash=window.location.hash] - Hash fragment of Url.
989 */
990 UserAgentApplication.prototype.processCallBack = function (hash, respStateInfo, parentCallback) {
991 this.logger.info("ProcessCallBack has been called. Processing callback from redirect response");
992 // get the state info from the hash
993 var stateInfo = respStateInfo;
994 if (!stateInfo) {
995 this.logger.verbose("StateInfo is null, getting stateInfo from hash");
996 stateInfo = this.getResponseState(hash);
997 }
998 var response;
999 var authErr;
1000 // Save the token info from the hash
1001 try {
1002 response = this.saveTokenFromHash(hash, stateInfo);
1003 }
1004 catch (err) {
1005 authErr = err;
1006 }
1007 try {
1008 // Clear the cookie in the hash
1009 this.cacheStorage.clearMsalCookie(stateInfo.state);
1010 var accountState = this.getAccountState(stateInfo.state);
1011 if (response) {
1012 if ((stateInfo.requestType === Constants_1.Constants.renewToken) || response.accessToken) {
1013 if (window.parent !== window) {
1014 this.logger.verbose("Window is in iframe, acquiring token silently");
1015 }
1016 else {
1017 this.logger.verbose("Acquiring token interactive in progress");
1018 }
1019 this.logger.verbose("Response tokenType set to " + Constants_1.ServerHashParamKeys.ACCESS_TOKEN);
1020 response.tokenType = Constants_1.ServerHashParamKeys.ACCESS_TOKEN;
1021 }
1022 else if (stateInfo.requestType === Constants_1.Constants.login) {
1023 this.logger.verbose("Response tokenType set to " + Constants_1.ServerHashParamKeys.ID_TOKEN);
1024 response.tokenType = Constants_1.ServerHashParamKeys.ID_TOKEN;
1025 }
1026 if (!parentCallback) {
1027 this.logger.verbose("Setting redirectResponse");
1028 this.redirectResponse = response;
1029 return;
1030 }
1031 }
1032 else if (!parentCallback) {
1033 this.logger.verbose("Response is null, setting redirectResponse with state");
1034 this.redirectResponse = AuthResponse_1.buildResponseStateOnly(accountState);
1035 this.redirectError = authErr;
1036 this.cacheStorage.resetTempCacheItems(stateInfo.state);
1037 return;
1038 }
1039 this.logger.verbose("Calling callback provided to processCallback");
1040 parentCallback(response, authErr);
1041 }
1042 catch (err) {
1043 this.logger.error("Error occurred in token received callback function: " + err);
1044 throw ClientAuthError_1.ClientAuthError.createErrorInCallbackFunction(err.toString());
1045 }
1046 };
1047 /**
1048 * @hidden
1049 * This method must be called for processing the response received from the STS if using popups or iframes. It extracts the hash, processes the token or error
1050 * information and saves it in the cache. It then resolves the promises with the result.
1051 * @param {string} [hash=window.location.hash] - Hash fragment of Url.
1052 */
1053 UserAgentApplication.prototype.handleAuthenticationResponse = function (hash) {
1054 this.logger.verbose("HandleAuthenticationResponse has been called");
1055 // retrieve the hash
1056 var locationHash = hash || window.location.hash;
1057 // if (window.parent !== window), by using self, window.parent becomes equal to window in getResponseState method specifically
1058 var stateInfo = this.getResponseState(locationHash);
1059 this.logger.verbose("Obtained state from response");
1060 var tokenResponseCallback = window.callbackMappedToRenewStates[stateInfo.state];
1061 this.processCallBack(locationHash, stateInfo, tokenResponseCallback);
1062 };
1063 /**
1064 * @hidden
1065 * This method must be called for processing the response received from the STS when using redirect flows. It extracts the hash, processes the token or error
1066 * information and saves it in the cache. The result can then be accessed by user registered callbacks.
1067 * @param {string} [hash=window.location.hash] - Hash fragment of Url.
1068 */
1069 UserAgentApplication.prototype.handleRedirectAuthenticationResponse = function (hash) {
1070 this.logger.info("Returned from redirect url");
1071 this.logger.verbose("HandleRedirectAuthenticationResponse has been called");
1072 // clear hash from window
1073 WindowUtils_1.WindowUtils.clearUrlFragment(window);
1074 this.logger.verbose("Window.location.hash cleared");
1075 // if (window.parent !== window), by using self, window.parent becomes equal to window in getResponseState method specifically
1076 var stateInfo = this.getResponseState(hash);
1077 // if set to navigate to loginRequest page post login
1078 if (this.config.auth.navigateToLoginRequestUrl && window.parent === window) {
1079 this.logger.verbose("Window.parent is equal to window, not in popup or iframe. Navigation to login request url after login turned on");
1080 var loginRequestUrl = this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.LOGIN_REQUEST, stateInfo.state), this.inCookie);
1081 // Redirect to home page if login request url is null (real null or the string null)
1082 if (!loginRequestUrl || loginRequestUrl === "null") {
1083 this.logger.error("Unable to get valid login request url from cache, redirecting to home page");
1084 window.location.assign("/");
1085 return;
1086 }
1087 else {
1088 this.logger.verbose("Valid login request url obtained from cache");
1089 var currentUrl = UrlUtils_1.UrlUtils.removeHashFromUrl(window.location.href);
1090 var finalRedirectUrl = UrlUtils_1.UrlUtils.removeHashFromUrl(loginRequestUrl);
1091 if (currentUrl !== finalRedirectUrl) {
1092 this.logger.verbose("Current url is not login request url, navigating");
1093 this.logger.verbosePii("CurrentUrl: " + currentUrl + ", finalRedirectUrl: " + finalRedirectUrl);
1094 window.location.assign("" + finalRedirectUrl + hash);
1095 return;
1096 }
1097 else {
1098 this.logger.verbose("Current url matches login request url");
1099 var loginRequestUrlComponents = UrlUtils_1.UrlUtils.GetUrlComponents(loginRequestUrl);
1100 if (loginRequestUrlComponents.Hash) {
1101 this.logger.verbose("Login request url contains hash, resetting non-msal hash");
1102 window.location.hash = loginRequestUrlComponents.Hash;
1103 }
1104 }
1105 }
1106 }
1107 else if (!this.config.auth.navigateToLoginRequestUrl) {
1108 this.logger.verbose("Default navigation to start page after login turned off");
1109 }
1110 this.processCallBack(hash, stateInfo, null);
1111 };
1112 /**
1113 * @hidden
1114 * Creates a stateInfo object from the URL fragment and returns it.
1115 * @param {string} hash - Hash passed from redirect page
1116 * @returns {TokenResponse} an object created from the redirect response from AAD comprising of the keys - parameters, requestType, stateMatch, stateResponse and valid.
1117 * @ignore
1118 */
1119 UserAgentApplication.prototype.getResponseState = function (hash) {
1120 this.logger.verbose("GetResponseState has been called");
1121 var parameters = UrlUtils_1.UrlUtils.deserializeHash(hash);
1122 var stateResponse;
1123 if (!parameters) {
1124 throw AuthError_1.AuthError.createUnexpectedError("Hash was not parsed correctly.");
1125 }
1126 if (parameters.hasOwnProperty(Constants_1.ServerHashParamKeys.STATE)) {
1127 this.logger.verbose("Hash contains state. Creating stateInfo object");
1128 var parsedState = RequestUtils_1.RequestUtils.parseLibraryState(parameters["state"]);
1129 stateResponse = {
1130 requestType: Constants_1.Constants.unknown,
1131 state: parameters["state"],
1132 timestamp: parsedState.ts,
1133 method: parsedState.method,
1134 stateMatch: false
1135 };
1136 }
1137 else {
1138 throw AuthError_1.AuthError.createUnexpectedError("Hash does not contain state.");
1139 }
1140 /*
1141 * async calls can fire iframe and login request at the same time if developer does not use the API as expected
1142 * incoming callback needs to be looked up to find the request type
1143 */
1144 // loginRedirect
1145 if (stateResponse.state === this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.STATE_LOGIN, stateResponse.state), this.inCookie) || stateResponse.state === this.silentAuthenticationState) {
1146 this.logger.verbose("State matches cached state, setting requestType to login");
1147 stateResponse.requestType = Constants_1.Constants.login;
1148 stateResponse.stateMatch = true;
1149 return stateResponse;
1150 }
1151 // acquireTokenRedirect
1152 else if (stateResponse.state === this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.STATE_ACQ_TOKEN, stateResponse.state), this.inCookie)) {
1153 this.logger.verbose("State matches cached state, setting requestType to renewToken");
1154 stateResponse.requestType = Constants_1.Constants.renewToken;
1155 stateResponse.stateMatch = true;
1156 return stateResponse;
1157 }
1158 // external api requests may have many renewtoken requests for different resource
1159 if (!stateResponse.stateMatch) {
1160 this.logger.verbose("State does not match cached state, setting requestType to type from window");
1161 stateResponse.requestType = window.requestType;
1162 var statesInParentContext = window.renewStates;
1163 for (var i = 0; i < statesInParentContext.length; i++) {
1164 if (statesInParentContext[i] === stateResponse.state) {
1165 this.logger.verbose("Matching state found for request");
1166 stateResponse.stateMatch = true;
1167 break;
1168 }
1169 }
1170 if (!stateResponse.stateMatch) {
1171 this.logger.verbose("Matching state not found for request");
1172 }
1173 }
1174 return stateResponse;
1175 };
1176 // #endregion
1177 // #region Token Processing (Extract to TokenProcessing.ts)
1178 /**
1179 * @hidden
1180 * Used to get token for the specified set of scopes from the cache
1181 * @param {@link ServerRequestParameters} - Request sent to the STS to obtain an id_token/access_token
1182 * @param {Account} account - Account for which the scopes were requested
1183 */
1184 UserAgentApplication.prototype.getCachedToken = function (serverAuthenticationRequest, account) {
1185 this.logger.verbose("GetCachedToken has been called");
1186 var scopes = serverAuthenticationRequest.scopes;
1187 /**
1188 * Id Token should be returned in every acquireTokenSilent call. The only exception is a response_type = token
1189 * request when a valid ID Token is not present in the cache.
1190 */
1191 var idToken = this.getCachedIdToken(serverAuthenticationRequest, account);
1192 var authResponse = this.getCachedAccessToken(serverAuthenticationRequest, account, scopes);
1193 var accountState = this.getAccountState(serverAuthenticationRequest.state);
1194 return ResponseUtils_1.ResponseUtils.buildAuthResponse(idToken, authResponse, serverAuthenticationRequest, account, scopes, accountState);
1195 };
1196 /**
1197 * @hidden
1198 *
1199 * Uses passed in authority to further filter an array of tokenCacheItems until only the token being searched for remains, then returns that tokenCacheItem.
1200 * This method will throw if authority filtering still yields multiple matching tokens and will return null if not tokens match the authority passed in.
1201 *
1202 * @param authority
1203 * @param tokenCacheItems
1204 * @param request
1205 * @param requestScopes
1206 * @param tokenType
1207 */
1208 UserAgentApplication.prototype.getTokenCacheItemByAuthority = function (authority, tokenCacheItems, requestScopes, tokenType) {
1209 var _this = this;
1210 var filteredAuthorityItems;
1211 if (UrlUtils_1.UrlUtils.isCommonAuthority(authority) || UrlUtils_1.UrlUtils.isOrganizationsAuthority(authority) || UrlUtils_1.UrlUtils.isConsumersAuthority(authority)) {
1212 filteredAuthorityItems = AuthCacheUtils_1.AuthCacheUtils.filterTokenCacheItemsByDomain(tokenCacheItems, UrlUtils_1.UrlUtils.GetUrlComponents(authority).HostNameAndPort);
1213 }
1214 else {
1215 filteredAuthorityItems = AuthCacheUtils_1.AuthCacheUtils.filterTokenCacheItemsByAuthority(tokenCacheItems, authority);
1216 }
1217 if (filteredAuthorityItems.length === 1) {
1218 return filteredAuthorityItems[0];
1219 }
1220 else if (filteredAuthorityItems.length > 1) {
1221 this.logger.warning("Multiple matching tokens found. Cleaning cache and requesting a new token.");
1222 filteredAuthorityItems.forEach(function (accessTokenCacheItem) {
1223 _this.cacheStorage.removeItem(JSON.stringify(accessTokenCacheItem.key));
1224 });
1225 return null;
1226 }
1227 else {
1228 this.logger.verbose("No matching tokens of type " + tokenType + " found");
1229 return null;
1230 }
1231 };
1232 /**
1233 *
1234 * @hidden
1235 *
1236 * Searches the token cache for an ID Token that matches the request parameter and returns it as an IdToken object.
1237 *
1238 * @param serverAuthenticationRequest
1239 * @param account
1240 */
1241 UserAgentApplication.prototype.getCachedIdToken = function (serverAuthenticationRequest, account) {
1242 this.logger.verbose("Getting all cached tokens of type ID Token");
1243 var idTokenCacheItems = this.cacheStorage.getAllIdTokens(this.clientId, account ? account.homeAccountIdentifier : null);
1244 var matchAuthority = serverAuthenticationRequest.authority || this.authority;
1245 var idTokenCacheItem = this.getTokenCacheItemByAuthority(matchAuthority, idTokenCacheItems, null, Constants_1.ServerHashParamKeys.ID_TOKEN);
1246 if (idTokenCacheItem) {
1247 this.logger.verbose("Evaluating ID token found");
1248 var idTokenIsStillValid = this.evaluateTokenExpiration(idTokenCacheItem);
1249 if (idTokenIsStillValid) {
1250 this.logger.verbose("ID token expiration is within offset, using ID token found in cache");
1251 var idTokenValue = idTokenCacheItem.value;
1252 if (idTokenValue) {
1253 this.logger.verbose("ID Token found in cache is valid and unexpired");
1254 }
1255 else {
1256 this.logger.verbose("ID Token found in cache is invalid");
1257 }
1258 return (idTokenValue) ? new IdToken_1.IdToken(idTokenValue.idToken) : null;
1259 }
1260 else {
1261 this.logger.verbose("Cached ID token is expired, removing from cache");
1262 this.cacheStorage.removeItem(JSON.stringify(idTokenCacheItem.key));
1263 return null;
1264 }
1265 }
1266 else {
1267 this.logger.verbose("No tokens found");
1268 return null;
1269 }
1270 };
1271 /**
1272 *
1273 * @hidden
1274 *
1275 * Searches the token cache for an access token that matches the request parameters and returns it as an AuthResponse.
1276 *
1277 * @param serverAuthenticationRequest
1278 * @param account
1279 * @param scopes
1280 */
1281 UserAgentApplication.prototype.getCachedAccessToken = function (serverAuthenticationRequest, account, scopes) {
1282 this.logger.verbose("Getting all cached tokens of type Access Token");
1283 var tokenCacheItems = this.cacheStorage.getAllAccessTokens(this.clientId, account ? account.homeAccountIdentifier : null);
1284 var scopeFilteredTokenCacheItems = AuthCacheUtils_1.AuthCacheUtils.filterTokenCacheItemsByScope(tokenCacheItems, scopes);
1285 var matchAuthority = serverAuthenticationRequest.authority || this.authority;
1286 // serverAuthenticationRequest.authority can only be common or organizations if not null
1287 var accessTokenCacheItem = this.getTokenCacheItemByAuthority(matchAuthority, scopeFilteredTokenCacheItems, scopes, Constants_1.ServerHashParamKeys.ACCESS_TOKEN);
1288 if (!accessTokenCacheItem) {
1289 this.logger.verbose("No matching token found when filtering by scope and authority");
1290 return null;
1291 }
1292 else {
1293 serverAuthenticationRequest.authorityInstance = AuthorityFactory_1.AuthorityFactory.CreateInstance(accessTokenCacheItem.key.authority, this.config.auth.validateAuthority);
1294 this.logger.verbose("Evaluating access token found");
1295 var tokenIsStillValid = this.evaluateTokenExpiration(accessTokenCacheItem);
1296 // The response value will stay null if token retrieved from the cache is expired, otherwise it will be populated with said token's data
1297 if (tokenIsStillValid) {
1298 this.logger.verbose("Access token expiration is within offset, using access token found in cache");
1299 var responseAccount = account || this.getAccount();
1300 if (!responseAccount) {
1301 throw AuthError_1.AuthError.createUnexpectedError("Account should not be null here.");
1302 }
1303 var aState = this.getAccountState(serverAuthenticationRequest.state);
1304 var response = {
1305 uniqueId: "",
1306 tenantId: "",
1307 tokenType: Constants_1.ServerHashParamKeys.ACCESS_TOKEN,
1308 idToken: null,
1309 idTokenClaims: null,
1310 accessToken: accessTokenCacheItem.value.accessToken,
1311 scopes: accessTokenCacheItem.key.scopes.split(" "),
1312 expiresOn: new Date(Number(accessTokenCacheItem.value.expiresIn) * 1000),
1313 account: responseAccount,
1314 accountState: aState,
1315 fromCache: true
1316 };
1317 return response;
1318 }
1319 else {
1320 this.logger.verbose("Access token expired, removing from cache");
1321 this.cacheStorage.removeItem(JSON.stringify(accessTokenCacheItem.key));
1322 return null;
1323 }
1324 }
1325 };
1326 /**
1327 * Returns true if the token passed in is within the acceptable expiration time offset, false if it is expired.
1328 * @param tokenCacheItem
1329 * @param serverAuthenticationRequest
1330 */
1331 UserAgentApplication.prototype.evaluateTokenExpiration = function (tokenCacheItem) {
1332 var expiration = Number(tokenCacheItem.value.expiresIn);
1333 return TokenUtils_1.TokenUtils.validateExpirationIsWithinOffset(expiration, this.config.system.tokenRenewalOffsetSeconds);
1334 };
1335 /**
1336 * @hidden
1337 * Check if ADAL id_token exists and return if exists.
1338 *
1339 */
1340 UserAgentApplication.prototype.extractADALIdToken = function () {
1341 this.logger.verbose("ExtractADALIdToken has been called");
1342 var adalIdToken = this.cacheStorage.getItem(Constants_1.Constants.adalIdToken);
1343 return (!StringUtils_1.StringUtils.isEmpty(adalIdToken)) ? TokenUtils_1.TokenUtils.extractIdToken(adalIdToken) : null;
1344 };
1345 /**
1346 * @hidden
1347 * Acquires access token using a hidden iframe.
1348 * @ignore
1349 */
1350 UserAgentApplication.prototype.renewToken = function (requestSignature, resolve, reject, account, serverAuthenticationRequest) {
1351 this.logger.verbose("RenewToken has been called");
1352 this.logger.verbosePii("RenewToken scope and authority: " + requestSignature);
1353 var frameName = WindowUtils_1.WindowUtils.generateFrameName(Constants_1.FramePrefix.TOKEN_FRAME, requestSignature);
1354 WindowUtils_1.WindowUtils.addHiddenIFrame(frameName, this.logger);
1355 this.updateCacheEntries(serverAuthenticationRequest, account, false);
1356 this.logger.verbosePii("RenewToken expected state: " + serverAuthenticationRequest.state);
1357 // Build urlNavigate with "prompt=none" and navigate to URL in hidden iFrame
1358 var urlNavigate = UrlUtils_1.UrlUtils.urlRemoveQueryStringParameter(UrlUtils_1.UrlUtils.createNavigateUrl(serverAuthenticationRequest), Constants_1.Constants.prompt) + Constants_1.Constants.prompt_none + Constants_1.Constants.response_mode_fragment;
1359 window.renewStates.push(serverAuthenticationRequest.state);
1360 window.requestType = Constants_1.Constants.renewToken;
1361 this.logger.verbose("Set window.renewState and requestType");
1362 this.registerCallback(serverAuthenticationRequest.state, requestSignature, resolve, reject);
1363 this.logger.infoPii("Navigate to: " + urlNavigate);
1364 this.loadIframeTimeout(urlNavigate, frameName, requestSignature).catch(function (error) { return reject(error); });
1365 };
1366 /**
1367 * @hidden
1368 * Renews idtoken for app's own backend when clientId is passed as a single scope in the scopes array.
1369 * @ignore
1370 */
1371 UserAgentApplication.prototype.renewIdToken = function (requestSignature, resolve, reject, account, serverAuthenticationRequest) {
1372 this.logger.info("RenewIdToken has been called");
1373 var frameName = WindowUtils_1.WindowUtils.generateFrameName(Constants_1.FramePrefix.ID_TOKEN_FRAME, requestSignature);
1374 WindowUtils_1.WindowUtils.addHiddenIFrame(frameName, this.logger);
1375 this.updateCacheEntries(serverAuthenticationRequest, account, false);
1376 this.logger.verbose("RenewIdToken expected state: " + serverAuthenticationRequest.state);
1377 // Build urlNavigate with "prompt=none" and navigate to URL in hidden iFrame
1378 var urlNavigate = UrlUtils_1.UrlUtils.urlRemoveQueryStringParameter(UrlUtils_1.UrlUtils.createNavigateUrl(serverAuthenticationRequest), Constants_1.Constants.prompt) + Constants_1.Constants.prompt_none + Constants_1.Constants.response_mode_fragment;
1379 if (this.silentLogin) {
1380 this.logger.verbose("Silent login is true, set silentAuthenticationState");
1381 window.requestType = Constants_1.Constants.login;
1382 this.silentAuthenticationState = serverAuthenticationRequest.state;
1383 }
1384 else {
1385 this.logger.verbose("Not silent login, set window.renewState and requestType");
1386 window.requestType = Constants_1.Constants.renewToken;
1387 window.renewStates.push(serverAuthenticationRequest.state);
1388 }
1389 // note: scope here is clientId
1390 this.registerCallback(serverAuthenticationRequest.state, requestSignature, resolve, reject);
1391 this.logger.infoPii("Navigate to:\" " + urlNavigate);
1392 this.loadIframeTimeout(urlNavigate, frameName, requestSignature).catch(function (error) { return reject(error); });
1393 };
1394 /**
1395 * @hidden
1396 *
1397 * This method builds an Access Token Cache item and saves it to the cache, returning the original
1398 * AuthResponse augmented with a parsed expiresOn attribute.
1399 *
1400 * @param response The AuthResponse object that contains the token to be saved
1401 * @param authority The authority under which the ID token will be cached
1402 * @param scopes The scopes to be added to the cache item key (undefined for ID token cache items)
1403 * @param clientInfo Client Info object that is used to generate the homeAccountIdentifier
1404 * @param expiration Token expiration timestamp
1405 */
1406 UserAgentApplication.prototype.saveToken = function (response, authority, scopes, clientInfo, expiration) {
1407 var accessTokenKey = new AccessTokenKey_1.AccessTokenKey(authority, this.clientId, scopes, clientInfo.uid, clientInfo.utid);
1408 var accessTokenValue = new AccessTokenValue_1.AccessTokenValue(response.accessToken, response.idToken.rawIdToken, expiration.toString(), clientInfo.encodeClientInfo());
1409 this.cacheStorage.setItem(JSON.stringify(accessTokenKey), JSON.stringify(accessTokenValue));
1410 if (expiration) {
1411 this.logger.verbose("New expiration set for token");
1412 response.expiresOn = new Date(expiration * 1000);
1413 }
1414 else {
1415 this.logger.error("Could not parse expiresIn parameter for access token");
1416 }
1417 return response;
1418 };
1419 /**
1420 * @hidden
1421 *
1422 * This method sets up the elements of an ID Token cache item and calls saveToken to save it in
1423 * Access Token Cache item format for the client application to use.
1424 *
1425 * @param response The AuthResponse object that will be used to build the cache item
1426 * @param authority The authority under which the ID token will be cached
1427 * @param parameters The response's Hash Params, which contain the ID token returned from the server
1428 * @param clientInfo Client Info object that is used to generate the homeAccountIdentifier
1429 * @param idTokenObj ID Token object from which the ID token's expiration is extracted
1430 */
1431 /* tslint:disable:no-string-literal */
1432 UserAgentApplication.prototype.saveIdToken = function (response, authority, parameters, clientInfo, idTokenObj) {
1433 this.logger.verbose("SaveIdToken has been called");
1434 var idTokenResponse = tslib_1.__assign({}, response);
1435 // Scopes are undefined so they don't show up in ID token cache key
1436 var scopes;
1437 idTokenResponse.scopes = Constants_1.Constants.oidcScopes;
1438 idTokenResponse.accessToken = parameters[Constants_1.ServerHashParamKeys.ID_TOKEN];
1439 var expiration = Number(idTokenObj.expiration);
1440 // Set ID Token item in cache
1441 this.logger.verbose("Saving ID token to cache");
1442 return this.saveToken(idTokenResponse, authority, scopes, clientInfo, expiration);
1443 };
1444 /**
1445 * @hidden
1446 *
1447 * This method sets up the elements of an Access Token cache item and calls saveToken to save it to the cache
1448 *
1449 * @param response The AuthResponse object that will be used to build the cache item
1450 * @param authority The authority under which the access token will be cached
1451 * @param parameters The response's Hash Params, which contain the access token returned from the server
1452 * @param clientInfo Client Info object that is used to generate the homeAccountIdentifier
1453 */
1454 /* tslint:disable:no-string-literal */
1455 UserAgentApplication.prototype.saveAccessToken = function (response, authority, parameters, clientInfo) {
1456 this.logger.verbose("SaveAccessToken has been called");
1457 var accessTokenResponse = tslib_1.__assign({}, response);
1458 // read the scopes
1459 var scope = parameters[Constants_1.ServerHashParamKeys.SCOPE];
1460 var consentedScopes = scope.split(" ");
1461 // retrieve all access tokens from the cache, remove the dup scopes
1462 var accessTokenCacheItems = this.cacheStorage.getAllAccessTokens(this.clientId, authority);
1463 this.logger.verbose("Retrieving all access tokens from cache and removing duplicates");
1464 for (var i = 0; i < accessTokenCacheItems.length; i++) {
1465 var accessTokenCacheItem = accessTokenCacheItems[i];
1466 if (accessTokenCacheItem.key.homeAccountIdentifier === response.account.homeAccountIdentifier) {
1467 var cachedScopes = accessTokenCacheItem.key.scopes.split(" ");
1468 if (ScopeSet_1.ScopeSet.isIntersectingScopes(cachedScopes, consentedScopes)) {
1469 this.cacheStorage.removeItem(JSON.stringify(accessTokenCacheItem.key));
1470 }
1471 }
1472 }
1473 accessTokenResponse.accessToken = parameters[Constants_1.ServerHashParamKeys.ACCESS_TOKEN];
1474 accessTokenResponse.scopes = consentedScopes;
1475 var expiresIn = TimeUtils_1.TimeUtils.parseExpiresIn(parameters[Constants_1.ServerHashParamKeys.EXPIRES_IN]);
1476 var parsedState = RequestUtils_1.RequestUtils.parseLibraryState(parameters[Constants_1.ServerHashParamKeys.STATE]);
1477 var expiration = parsedState.ts + expiresIn;
1478 this.logger.verbose("Saving access token to cache");
1479 return this.saveToken(accessTokenResponse, authority, scope, clientInfo, expiration);
1480 };
1481 /**
1482 * @hidden
1483 * Saves token or error received in the response from AAD in the cache. In case of id_token, it also creates the account object.
1484 * @ignore
1485 */
1486 UserAgentApplication.prototype.saveTokenFromHash = function (hash, stateInfo) {
1487 this.logger.verbose("SaveTokenFromHash has been called");
1488 this.logger.info("State status: " + stateInfo.stateMatch + "; Request type: " + stateInfo.requestType);
1489 var response = {
1490 uniqueId: "",
1491 tenantId: "",
1492 tokenType: "",
1493 idToken: null,
1494 idTokenClaims: null,
1495 accessToken: null,
1496 scopes: [],
1497 expiresOn: null,
1498 account: null,
1499 accountState: "",
1500 fromCache: false
1501 };
1502 var error;
1503 var hashParams = UrlUtils_1.UrlUtils.deserializeHash(hash);
1504 var authorityKey = "";
1505 var acquireTokenAccountKey = "";
1506 var idTokenObj = null;
1507 // If server returns an error
1508 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION) || hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.ERROR)) {
1509 this.logger.verbose("Server returned an error");
1510 this.logger.infoPii("Error : " + hashParams[Constants_1.ServerHashParamKeys.ERROR] + "; Error description: " + hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION]);
1511 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR, hashParams[Constants_1.ServerHashParamKeys.ERROR]);
1512 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR_DESC, hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION]);
1513 // login
1514 if (stateInfo.requestType === Constants_1.Constants.login) {
1515 this.logger.verbose("RequestType is login, caching login error, generating authorityKey");
1516 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.LOGIN_ERROR, hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION] + ":" + hashParams[Constants_1.ServerHashParamKeys.ERROR]);
1517 authorityKey = AuthCache_1.AuthCache.generateAuthorityKey(stateInfo.state);
1518 }
1519 // acquireToken
1520 if (stateInfo.requestType === Constants_1.Constants.renewToken) {
1521 this.logger.verbose("RequestType is renewToken, generating acquireTokenAccountKey");
1522 authorityKey = AuthCache_1.AuthCache.generateAuthorityKey(stateInfo.state);
1523 var account = this.getAccount();
1524 var accountId = void 0;
1525 if (account && !StringUtils_1.StringUtils.isEmpty(account.homeAccountIdentifier)) {
1526 accountId = account.homeAccountIdentifier;
1527 this.logger.verbose("AccountId is set");
1528 }
1529 else {
1530 accountId = Constants_1.Constants.no_account;
1531 this.logger.verbose("AccountId is set as no_account");
1532 }
1533 acquireTokenAccountKey = AuthCache_1.AuthCache.generateAcquireTokenAccountKey(accountId, stateInfo.state);
1534 }
1535 var hashErr = hashParams[Constants_1.ServerHashParamKeys.ERROR];
1536 var hashErrDesc = hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION];
1537 if (InteractionRequiredAuthError_1.InteractionRequiredAuthError.isInteractionRequiredError(hashErr) ||
1538 InteractionRequiredAuthError_1.InteractionRequiredAuthError.isInteractionRequiredError(hashErrDesc)) {
1539 error = new InteractionRequiredAuthError_1.InteractionRequiredAuthError(hashParams[Constants_1.ServerHashParamKeys.ERROR], hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION]);
1540 }
1541 else {
1542 error = new ServerError_1.ServerError(hashParams[Constants_1.ServerHashParamKeys.ERROR], hashParams[Constants_1.ServerHashParamKeys.ERROR_DESCRIPTION]);
1543 }
1544 }
1545 // If the server returns "Success"
1546 else {
1547 this.logger.verbose("Server returns success");
1548 // Verify the state from redirect and record tokens to storage if exists
1549 if (stateInfo.stateMatch) {
1550 this.logger.info("State is right");
1551 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.SESSION_STATE)) {
1552 this.logger.verbose("Fragment has session state, caching");
1553 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.SESSION_STATE, stateInfo.state), hashParams[Constants_1.ServerHashParamKeys.SESSION_STATE]);
1554 }
1555 response.accountState = this.getAccountState(stateInfo.state);
1556 var clientInfo = void 0;
1557 // Process access_token
1558 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.ACCESS_TOKEN)) {
1559 this.logger.info("Fragment has access token");
1560 response.accessToken = hashParams[Constants_1.ServerHashParamKeys.ACCESS_TOKEN];
1561 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.SCOPE)) {
1562 response.scopes = hashParams[Constants_1.ServerHashParamKeys.SCOPE].split(" ");
1563 }
1564 // retrieve the id_token from response if present
1565 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.ID_TOKEN)) {
1566 this.logger.verbose("Fragment has id_token");
1567 idTokenObj = new IdToken_1.IdToken(hashParams[Constants_1.ServerHashParamKeys.ID_TOKEN]);
1568 }
1569 else {
1570 this.logger.verbose("No idToken on fragment, getting idToken from cache");
1571 idTokenObj = new IdToken_1.IdToken(this.cacheStorage.getItem(Constants_1.PersistentCacheKeys.IDTOKEN));
1572 }
1573 response = ResponseUtils_1.ResponseUtils.setResponseIdToken(response, idTokenObj);
1574 // set authority
1575 var authority = this.populateAuthority(stateInfo.state, this.inCookie, this.cacheStorage, idTokenObj);
1576 this.logger.verbose("Got authority from cache");
1577 // retrieve client_info - if it is not found, generate the uid and utid from idToken
1578 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.CLIENT_INFO)) {
1579 this.logger.verbose("Fragment has clientInfo");
1580 clientInfo = new ClientInfo_1.ClientInfo(hashParams[Constants_1.ServerHashParamKeys.CLIENT_INFO], authority);
1581 }
1582 else if (this.authorityInstance.AuthorityType === Authority_1.AuthorityType.Adfs) {
1583 clientInfo = ClientInfo_1.ClientInfo.createClientInfoFromIdToken(idTokenObj, authority);
1584 }
1585 else {
1586 this.logger.warning("ClientInfo not received in the response from AAD");
1587 }
1588 response.account = Account_1.Account.createAccount(idTokenObj, clientInfo);
1589 this.logger.verbose("Account object created from response");
1590 var accountKey = void 0;
1591 if (response.account && !StringUtils_1.StringUtils.isEmpty(response.account.homeAccountIdentifier)) {
1592 this.logger.verbose("AccountKey set");
1593 accountKey = response.account.homeAccountIdentifier;
1594 }
1595 else {
1596 this.logger.verbose("AccountKey set as no_account");
1597 accountKey = Constants_1.Constants.no_account;
1598 }
1599 acquireTokenAccountKey = AuthCache_1.AuthCache.generateAcquireTokenAccountKey(accountKey, stateInfo.state);
1600 var acquireTokenAccountKey_noaccount = AuthCache_1.AuthCache.generateAcquireTokenAccountKey(Constants_1.Constants.no_account, stateInfo.state);
1601 this.logger.verbose("AcquireTokenAccountKey generated");
1602 var cachedAccount = this.cacheStorage.getItem(acquireTokenAccountKey);
1603 var acquireTokenAccount = void 0;
1604 // Check with the account in the Cache
1605 if (!StringUtils_1.StringUtils.isEmpty(cachedAccount)) {
1606 acquireTokenAccount = JSON.parse(cachedAccount);
1607 this.logger.verbose("AcquireToken request account retrieved from cache");
1608 if (response.account && acquireTokenAccount && Account_1.Account.compareAccounts(response.account, acquireTokenAccount)) {
1609 response = this.saveAccessToken(response, authority, hashParams, clientInfo);
1610 this.logger.info("The user object received in the response is the same as the one passed in the acquireToken request");
1611 }
1612 else {
1613 this.logger.warning("The account object created from the response is not the same as the one passed in the acquireToken request");
1614 }
1615 }
1616 else if (!StringUtils_1.StringUtils.isEmpty(this.cacheStorage.getItem(acquireTokenAccountKey_noaccount))) {
1617 this.logger.verbose("No acquireToken account retrieved from cache");
1618 response = this.saveAccessToken(response, authority, hashParams, clientInfo);
1619 }
1620 }
1621 // Process id_token
1622 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.ID_TOKEN)) {
1623 this.logger.info("Fragment has idToken");
1624 // set the idToken
1625 idTokenObj = new IdToken_1.IdToken(hashParams[Constants_1.ServerHashParamKeys.ID_TOKEN]);
1626 // set authority
1627 var authority = this.populateAuthority(stateInfo.state, this.inCookie, this.cacheStorage, idTokenObj);
1628 response = ResponseUtils_1.ResponseUtils.setResponseIdToken(response, idTokenObj);
1629 if (hashParams.hasOwnProperty(Constants_1.ServerHashParamKeys.CLIENT_INFO)) {
1630 this.logger.verbose("Fragment has clientInfo");
1631 clientInfo = new ClientInfo_1.ClientInfo(hashParams[Constants_1.ServerHashParamKeys.CLIENT_INFO], authority);
1632 }
1633 else if (this.authorityInstance.AuthorityType === Authority_1.AuthorityType.Adfs) {
1634 clientInfo = ClientInfo_1.ClientInfo.createClientInfoFromIdToken(idTokenObj, authority);
1635 }
1636 else {
1637 this.logger.warning("ClientInfo not received in the response from AAD");
1638 }
1639 this.account = Account_1.Account.createAccount(idTokenObj, clientInfo);
1640 response.account = this.account;
1641 this.logger.verbose("Account object created from response");
1642 if (idTokenObj && idTokenObj.nonce) {
1643 this.logger.verbose("IdToken has nonce");
1644 // check nonce integrity if idToken has nonce - throw an error if not matched
1645 var cachedNonce = this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.NONCE_IDTOKEN, stateInfo.state), this.inCookie);
1646 if (idTokenObj.nonce !== cachedNonce) {
1647 this.account = null;
1648 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.LOGIN_ERROR, "Nonce Mismatch. Expected Nonce: " + cachedNonce + "," + "Actual Nonce: " + idTokenObj.nonce);
1649 this.logger.error("Nonce Mismatch. Expected Nonce: " + cachedNonce + ", Actual Nonce: " + idTokenObj.nonce);
1650 error = ClientAuthError_1.ClientAuthError.createNonceMismatchError(cachedNonce, idTokenObj.nonce);
1651 }
1652 // Save the token
1653 else {
1654 this.logger.verbose("Nonce matches, saving idToken to cache");
1655 this.cacheStorage.setItem(Constants_1.PersistentCacheKeys.IDTOKEN, hashParams[Constants_1.ServerHashParamKeys.ID_TOKEN], this.inCookie);
1656 this.cacheStorage.setItem(Constants_1.PersistentCacheKeys.CLIENT_INFO, clientInfo.encodeClientInfo(), this.inCookie);
1657 // Save idToken as access token item for app itself
1658 this.saveIdToken(response, authority, hashParams, clientInfo, idTokenObj);
1659 }
1660 }
1661 else {
1662 this.logger.verbose("No idToken or no nonce. Cache key for Authority set as state");
1663 authorityKey = stateInfo.state;
1664 acquireTokenAccountKey = stateInfo.state;
1665 this.logger.error("Invalid id_token received in the response");
1666 error = ClientAuthError_1.ClientAuthError.createInvalidIdTokenError(idTokenObj);
1667 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR, error.errorCode);
1668 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR_DESC, error.errorMessage);
1669 }
1670 }
1671 }
1672 // State mismatch - unexpected/invalid state
1673 else {
1674 this.logger.verbose("State mismatch");
1675 authorityKey = stateInfo.state;
1676 acquireTokenAccountKey = stateInfo.state;
1677 var expectedState = this.cacheStorage.getItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.STATE_LOGIN, stateInfo.state), this.inCookie);
1678 this.logger.error("State Mismatch. Expected State: " + expectedState + ", Actual State: " + stateInfo.state);
1679 error = ClientAuthError_1.ClientAuthError.createInvalidStateError(stateInfo.state, expectedState);
1680 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR, error.errorCode);
1681 this.cacheStorage.setItem(Constants_1.ErrorCacheKeys.ERROR_DESC, error.errorMessage);
1682 }
1683 }
1684 // Set status to completed
1685 this.cacheStorage.removeItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.RENEW_STATUS, stateInfo.state));
1686 this.cacheStorage.resetTempCacheItems(stateInfo.state);
1687 this.logger.verbose("Status set to complete, temporary cache cleared");
1688 // this is required if navigateToLoginRequestUrl=false
1689 if (this.inCookie) {
1690 this.logger.verbose("InCookie is true, setting authorityKey in cookie");
1691 this.cacheStorage.setItemCookie(authorityKey, "", -1);
1692 this.cacheStorage.clearMsalCookie(stateInfo.state);
1693 }
1694 if (error) {
1695 // Error case, set status to cancelled
1696 throw error;
1697 }
1698 if (!response) {
1699 throw AuthError_1.AuthError.createUnexpectedError("Response is null");
1700 }
1701 return response;
1702 };
1703 /**
1704 * Set Authority when saving Token from the hash
1705 * @param state
1706 * @param inCookie
1707 * @param cacheStorage
1708 * @param idTokenObj
1709 * @param response
1710 */
1711 UserAgentApplication.prototype.populateAuthority = function (state, inCookie, cacheStorage, idTokenObj) {
1712 this.logger.verbose("PopulateAuthority has been called");
1713 var authorityKey = AuthCache_1.AuthCache.generateAuthorityKey(state);
1714 var cachedAuthority = cacheStorage.getItem(authorityKey, inCookie);
1715 // retrieve the authority from cache and replace with tenantID
1716 return StringUtils_1.StringUtils.isEmpty(cachedAuthority) ? cachedAuthority : UrlUtils_1.UrlUtils.replaceTenantPath(cachedAuthority, idTokenObj.tenantId);
1717 };
1718 /* tslint:enable:no-string-literal */
1719 // #endregion
1720 // #region Account
1721 /**
1722 * Returns the signed in account
1723 * (the account object is created at the time of successful login)
1724 * or null when no state is found
1725 * @returns {@link Account} - the account object stored in MSAL
1726 */
1727 UserAgentApplication.prototype.getAccount = function () {
1728 // if a session already exists, get the account from the session
1729 if (this.account) {
1730 return this.account;
1731 }
1732 // frame is used to get idToken and populate the account for the given session
1733 var rawIdToken = this.cacheStorage.getItem(Constants_1.PersistentCacheKeys.IDTOKEN, this.inCookie);
1734 var rawClientInfo = this.cacheStorage.getItem(Constants_1.PersistentCacheKeys.CLIENT_INFO, this.inCookie);
1735 if (!StringUtils_1.StringUtils.isEmpty(rawIdToken) && !StringUtils_1.StringUtils.isEmpty(rawClientInfo)) {
1736 var idToken = new IdToken_1.IdToken(rawIdToken);
1737 var clientInfo = new ClientInfo_1.ClientInfo(rawClientInfo, "");
1738 this.account = Account_1.Account.createAccount(idToken, clientInfo);
1739 return this.account;
1740 }
1741 // if login not yet done, return null
1742 return null;
1743 };
1744 /**
1745 * @hidden
1746 *
1747 * Extracts state value from the accountState sent with the authentication request.
1748 * @returns {string} scope.
1749 * @ignore
1750 */
1751 UserAgentApplication.prototype.getAccountState = function (state) {
1752 if (state) {
1753 var splitIndex = state.indexOf(Constants_1.Constants.resourceDelimiter);
1754 if (splitIndex > -1 && splitIndex + 1 < state.length) {
1755 return state.substring(splitIndex + 1);
1756 }
1757 }
1758 return state;
1759 };
1760 /**
1761 * Use to get a list of unique accounts in MSAL cache based on homeAccountIdentifier.
1762 *
1763 * @param {@link Array<Account>} Account - all unique accounts in MSAL cache.
1764 */
1765 UserAgentApplication.prototype.getAllAccounts = function () {
1766 var accounts = [];
1767 var accessTokenCacheItems = this.cacheStorage.getAllAccessTokens(Constants_1.Constants.clientId, Constants_1.Constants.homeAccountIdentifier);
1768 for (var i = 0; i < accessTokenCacheItems.length; i++) {
1769 var idToken = new IdToken_1.IdToken(accessTokenCacheItems[i].value.idToken);
1770 var clientInfo = new ClientInfo_1.ClientInfo(accessTokenCacheItems[i].value.homeAccountIdentifier, "");
1771 var account = Account_1.Account.createAccount(idToken, clientInfo);
1772 accounts.push(account);
1773 }
1774 return this.getUniqueAccounts(accounts);
1775 };
1776 /**
1777 * @hidden
1778 *
1779 * Used to filter accounts based on homeAccountIdentifier
1780 * @param {Array<Account>} Accounts - accounts saved in the cache
1781 * @ignore
1782 */
1783 UserAgentApplication.prototype.getUniqueAccounts = function (accounts) {
1784 if (!accounts || accounts.length <= 1) {
1785 return accounts;
1786 }
1787 var flags = [];
1788 var uniqueAccounts = [];
1789 for (var index = 0; index < accounts.length; ++index) {
1790 if (accounts[index].homeAccountIdentifier && flags.indexOf(accounts[index].homeAccountIdentifier) === -1) {
1791 flags.push(accounts[index].homeAccountIdentifier);
1792 uniqueAccounts.push(accounts[index]);
1793 }
1794 }
1795 return uniqueAccounts;
1796 };
1797 // #endregion
1798 // #region Angular
1799 /**
1800 * @hidden
1801 *
1802 * Broadcast messages - Used only for Angular? *
1803 * @param eventName
1804 * @param data
1805 */
1806 UserAgentApplication.prototype.broadcast = function (eventName, data) {
1807 var evt = new CustomEvent(eventName, { detail: data });
1808 window.dispatchEvent(evt);
1809 };
1810 /**
1811 * @hidden
1812 *
1813 * Helper function to retrieve the cached token
1814 *
1815 * @param scopes
1816 * @param {@link Account} account
1817 * @param state
1818 * @return {@link AuthResponse} AuthResponse
1819 */
1820 UserAgentApplication.prototype.getCachedTokenInternal = function (scopes, account, state, correlationId) {
1821 // Get the current session's account object
1822 var accountObject = account || this.getAccount();
1823 if (!accountObject) {
1824 return null;
1825 }
1826 // Construct AuthenticationRequest based on response type; set "redirectUri" from the "request" which makes this call from Angular - for this.getRedirectUri()
1827 var newAuthority = this.authorityInstance ? this.authorityInstance : AuthorityFactory_1.AuthorityFactory.CreateInstance(this.authority, this.config.auth.validateAuthority);
1828 var responseType = this.getTokenType(accountObject, scopes);
1829 var serverAuthenticationRequest = new ServerRequestParameters_1.ServerRequestParameters(newAuthority, this.clientId, responseType, this.getRedirectUri(), scopes, state, correlationId);
1830 // get cached token
1831 return this.getCachedToken(serverAuthenticationRequest, account);
1832 };
1833 /**
1834 * @hidden
1835 *
1836 * Get scopes for the Endpoint - Used in Angular to track protected and unprotected resources without interaction from the developer app
1837 * Note: Please check if we need to set the "redirectUri" from the "request" which makes this call from Angular - for this.getRedirectUri()
1838 *
1839 * @param endpoint
1840 */
1841 UserAgentApplication.prototype.getScopesForEndpoint = function (endpoint) {
1842 // if user specified list of unprotectedResources, no need to send token to these endpoints, return null.
1843 if (this.config.framework.unprotectedResources.length > 0) {
1844 for (var i = 0; i < this.config.framework.unprotectedResources.length; i++) {
1845 if (endpoint.indexOf(this.config.framework.unprotectedResources[i]) > -1) {
1846 return null;
1847 }
1848 }
1849 }
1850 // process all protected resources and send the matched one
1851 if (this.config.framework.protectedResourceMap.size > 0) {
1852 for (var _i = 0, _a = Array.from(this.config.framework.protectedResourceMap.keys()); _i < _a.length; _i++) {
1853 var key = _a[_i];
1854 // configEndpoint is like /api/Todo requested endpoint can be /api/Todo/1
1855 if (endpoint.indexOf(key) > -1) {
1856 return this.config.framework.protectedResourceMap.get(key);
1857 }
1858 }
1859 }
1860 /*
1861 * default resource will be clientid if nothing specified
1862 * App will use idtoken for calls to itself
1863 * check if it's staring from http or https, needs to match with app host
1864 */
1865 if (endpoint.indexOf("http://") > -1 || endpoint.indexOf("https://") > -1) {
1866 if (UrlUtils_1.UrlUtils.getHostFromUri(endpoint) === UrlUtils_1.UrlUtils.getHostFromUri(this.getRedirectUri())) {
1867 return new Array(this.clientId);
1868 }
1869 }
1870 else {
1871 /*
1872 * in angular level, the url for $http interceptor call could be relative url,
1873 * if it's relative call, we'll treat it as app backend call.
1874 */
1875 return new Array(this.clientId);
1876 }
1877 // if not the app's own backend or not a domain listed in the endpoints structure
1878 return null;
1879 };
1880 /**
1881 * Return boolean flag to developer to help inform if login is in progress
1882 * @returns {boolean} true/false
1883 */
1884 UserAgentApplication.prototype.getLoginInProgress = function () {
1885 return this.cacheStorage.isInteractionInProgress(true);
1886 };
1887 /**
1888 * @hidden
1889 * @ignore
1890 *
1891 * @param loginInProgress
1892 */
1893 UserAgentApplication.prototype.setInteractionInProgress = function (inProgress) {
1894 this.cacheStorage.setInteractionInProgress(inProgress);
1895 };
1896 /**
1897 * @hidden
1898 * @ignore
1899 *
1900 * @param loginInProgress
1901 */
1902 UserAgentApplication.prototype.setloginInProgress = function (loginInProgress) {
1903 this.setInteractionInProgress(loginInProgress);
1904 };
1905 /**
1906 * @hidden
1907 * @ignore
1908 *
1909 * returns the status of acquireTokenInProgress
1910 */
1911 UserAgentApplication.prototype.getAcquireTokenInProgress = function () {
1912 return this.cacheStorage.isInteractionInProgress(true);
1913 };
1914 /**
1915 * @hidden
1916 * @ignore
1917 *
1918 * @param acquireTokenInProgress
1919 */
1920 UserAgentApplication.prototype.setAcquireTokenInProgress = function (acquireTokenInProgress) {
1921 this.setInteractionInProgress(acquireTokenInProgress);
1922 };
1923 /**
1924 * @hidden
1925 * @ignore
1926 *
1927 * returns the logger handle
1928 */
1929 UserAgentApplication.prototype.getLogger = function () {
1930 return this.logger;
1931 };
1932 /**
1933 * Sets the logger callback.
1934 * @param logger Logger callback
1935 */
1936 UserAgentApplication.prototype.setLogger = function (logger) {
1937 this.logger = logger;
1938 };
1939 // #endregion
1940 // #region Getters and Setters
1941 /**
1942 * Use to get the redirect uri configured in MSAL or null.
1943 * Evaluates redirectUri if its a function, otherwise simply returns its value.
1944 *
1945 * @returns {string} redirect URL
1946 */
1947 UserAgentApplication.prototype.getRedirectUri = function (reqRedirectUri) {
1948 if (reqRedirectUri) {
1949 return reqRedirectUri;
1950 }
1951 else if (typeof this.config.auth.redirectUri === "function") {
1952 return this.config.auth.redirectUri();
1953 }
1954 return this.config.auth.redirectUri;
1955 };
1956 /**
1957 * Use to get the post logout redirect uri configured in MSAL or null.
1958 * Evaluates postLogoutredirectUri if its a function, otherwise simply returns its value.
1959 *
1960 * @returns {string} post logout redirect URL
1961 */
1962 UserAgentApplication.prototype.getPostLogoutRedirectUri = function () {
1963 if (typeof this.config.auth.postLogoutRedirectUri === "function") {
1964 return this.config.auth.postLogoutRedirectUri();
1965 }
1966 return this.config.auth.postLogoutRedirectUri;
1967 };
1968 /**
1969 * Use to get the current {@link Configuration} object in MSAL
1970 *
1971 * @returns {@link Configuration}
1972 */
1973 UserAgentApplication.prototype.getCurrentConfiguration = function () {
1974 if (!this.config) {
1975 throw ClientConfigurationError_1.ClientConfigurationError.createNoSetConfigurationError();
1976 }
1977 return this.config;
1978 };
1979 /**
1980 * @ignore
1981 *
1982 * Utils function to create the Authentication
1983 * @param {@link account} account object
1984 * @param scopes
1985 *
1986 * @returns {string} token type: token, id_token or id_token token
1987 *
1988 */
1989 UserAgentApplication.prototype.getTokenType = function (accountObject, scopes) {
1990 var accountsMatch = Account_1.Account.compareAccounts(accountObject, this.getAccount());
1991 return ServerRequestParameters_1.ServerRequestParameters.determineResponseType(accountsMatch, scopes);
1992 };
1993 /**
1994 * @hidden
1995 * @ignore
1996 *
1997 * Sets the cachekeys for and stores the account information in cache
1998 * @param account
1999 * @param state
2000 * @hidden
2001 */
2002 UserAgentApplication.prototype.setAccountCache = function (account, state) {
2003 // Cache acquireTokenAccountKey
2004 var accountId = account ? this.getAccountId(account) : Constants_1.Constants.no_account;
2005 var acquireTokenAccountKey = AuthCache_1.AuthCache.generateAcquireTokenAccountKey(accountId, state);
2006 this.cacheStorage.setItem(acquireTokenAccountKey, JSON.stringify(account));
2007 };
2008 /**
2009 * @hidden
2010 * @ignore
2011 *
2012 * Sets the cacheKey for and stores the authority information in cache
2013 * @param state
2014 * @param authority
2015 * @hidden
2016 */
2017 UserAgentApplication.prototype.setAuthorityCache = function (state, authority) {
2018 // Cache authorityKey
2019 var authorityKey = AuthCache_1.AuthCache.generateAuthorityKey(state);
2020 this.cacheStorage.setItem(authorityKey, UrlUtils_1.UrlUtils.CanonicalizeUri(authority), this.inCookie);
2021 };
2022 /**
2023 * Updates account, authority, and nonce in cache
2024 * @param serverAuthenticationRequest
2025 * @param account
2026 * @hidden
2027 * @ignore
2028 */
2029 UserAgentApplication.prototype.updateCacheEntries = function (serverAuthenticationRequest, account, isLoginCall, loginStartPage) {
2030 // Cache Request Originator Page
2031 if (loginStartPage) {
2032 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.LOGIN_REQUEST, serverAuthenticationRequest.state), loginStartPage, this.inCookie);
2033 }
2034 // Cache account and authority
2035 if (isLoginCall) {
2036 // Cache the state
2037 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.STATE_LOGIN, serverAuthenticationRequest.state), serverAuthenticationRequest.state, this.inCookie);
2038 }
2039 else {
2040 this.setAccountCache(account, serverAuthenticationRequest.state);
2041 }
2042 // Cache authorityKey
2043 this.setAuthorityCache(serverAuthenticationRequest.state, serverAuthenticationRequest.authority);
2044 // Cache nonce
2045 this.cacheStorage.setItem(AuthCache_1.AuthCache.generateTemporaryCacheKey(Constants_1.TemporaryCacheKeys.NONCE_IDTOKEN, serverAuthenticationRequest.state), serverAuthenticationRequest.nonce, this.inCookie);
2046 };
2047 /**
2048 * Returns the unique identifier for the logged in account
2049 * @param account
2050 * @hidden
2051 * @ignore
2052 */
2053 UserAgentApplication.prototype.getAccountId = function (account) {
2054 // return `${account.accountIdentifier}` + Constants.resourceDelimiter + `${account.homeAccountIdentifier}`;
2055 var accountId;
2056 if (!StringUtils_1.StringUtils.isEmpty(account.homeAccountIdentifier)) {
2057 accountId = account.homeAccountIdentifier;
2058 }
2059 else {
2060 accountId = Constants_1.Constants.no_account;
2061 }
2062 return accountId;
2063 };
2064 /**
2065 * @ignore
2066 * @param extraQueryParameters
2067 *
2068 * Construct 'tokenRequest' from the available data in adalIdToken
2069 */
2070 UserAgentApplication.prototype.buildIDTokenRequest = function (request) {
2071 var tokenRequest = {
2072 scopes: Constants_1.Constants.oidcScopes,
2073 authority: this.authority,
2074 account: this.getAccount(),
2075 extraQueryParameters: request.extraQueryParameters,
2076 correlationId: request.correlationId
2077 };
2078 return tokenRequest;
2079 };
2080 /**
2081 * @ignore
2082 * @param config
2083 * @param clientId
2084 *
2085 * Construct TelemetryManager from Configuration
2086 */
2087 UserAgentApplication.prototype.getTelemetryManagerFromConfig = function (config, clientId) {
2088 if (!config) { // if unset
2089 return TelemetryManager_1.default.getTelemetrymanagerStub(clientId, this.logger);
2090 }
2091 // if set then validate
2092 var applicationName = config.applicationName, applicationVersion = config.applicationVersion, telemetryEmitter = config.telemetryEmitter;
2093 if (!applicationName || !applicationVersion || !telemetryEmitter) {
2094 throw ClientConfigurationError_1.ClientConfigurationError.createTelemetryConfigError(config);
2095 }
2096 // if valid then construct
2097 var telemetryPlatform = {
2098 applicationName: applicationName,
2099 applicationVersion: applicationVersion
2100 };
2101 var telemetryManagerConfig = {
2102 platform: telemetryPlatform,
2103 clientId: clientId
2104 };
2105 return new TelemetryManager_1.default(telemetryManagerConfig, telemetryEmitter, this.logger);
2106 };
2107 return UserAgentApplication;
2108}());
2109exports.UserAgentApplication = UserAgentApplication;
2110//# sourceMappingURL=UserAgentApplication.js.map
\No newline at end of file