UNPKG

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