Skip to content

Commit c968ef7

Browse files
author
Prithvi Kanherkar
authored
Merge pull request #1762 from AzureAD/msal-node-cache-merge
[msal-node][#2] Merge cache logic in `msal-common` for `node` and `browser` platforms
2 parents 189cbe7 + e80a2ed commit c968ef7

File tree

71 files changed

+405
-2274
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+405
-2274
lines changed

lib/msal-browser/src/app/PublicClientApplication.ts

+42-30
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
* Licensed under the MIT License.
44
*/
55
import {
6-
IAccount,
76
SPAClient,
87
INetworkModule,
9-
TokenResponse,
108
UrlString,
11-
TokenRenewParameters,
129
StringUtils,
1310
PromptValue,
1411
ServerError,
@@ -24,9 +21,11 @@ import {
2421
Constants,
2522
ClientAuthError,
2623
AuthorityType,
24+
CacheSchemaType,
2725
AuthenticationResult,
2826
SilentFlowRequest,
29-
AccountEntity
27+
AccountEntity,
28+
IAccount
3029
} from "@azure/msal-common";
3130
import { buildConfiguration, Configuration } from "../config/Configuration";
3231
import { BrowserStorage } from "../cache/BrowserStorage";
@@ -65,6 +64,7 @@ export class PublicClientApplication {
6564
// Input configuration by developer/user
6665
private config: Configuration;
6766

67+
// Default authority
6868
protected defaultAuthorityInstance: Authority;
6969

7070
/**
@@ -197,10 +197,10 @@ export class PublicClientApplication {
197197
private async handleRedirectResponse(): Promise<AuthenticationResult> {
198198
// Get current location hash from window or cache.
199199
const {location: {hash}} = window;
200-
const cachedHash = this.browserStorage.getItem(TemporaryCacheKeys.URL_HASH);
200+
const cachedHash = this.browserStorage.getItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH), CacheSchemaType.TEMPORARY) as string;
201201
const isResponseHash = UrlString.hashContainsKnownProperties(hash);
202202

203-
const loginRequestUrl = this.browserStorage.getItem(TemporaryCacheKeys.ORIGIN_URI);
203+
const loginRequestUrl = this.browserStorage.getItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.ORIGIN_URI), CacheSchemaType.TEMPORARY) as string;
204204
const currentUrl = BrowserUtils.getCurrentUri();
205205
if (loginRequestUrl === currentUrl) {
206206
// We don't need to navigate - check for hash and prepare to process
@@ -215,7 +215,8 @@ export class PublicClientApplication {
215215

216216
if (this.config.auth.navigateToLoginRequestUrl && isResponseHash && !BrowserUtils.isInIframe()) {
217217
// Returned from authority using redirect - need to perform navigation before processing response
218-
this.browserStorage.setItem(TemporaryCacheKeys.URL_HASH, hash);
218+
const hashKey = this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH);
219+
this.browserStorage.setItem(hashKey, hash, CacheSchemaType.TEMPORARY);
219220

220221
if (StringUtils.isEmpty(loginRequestUrl) || loginRequestUrl === "null") {
221222
// Redirect to home page if login request url is null (real null or the string null)
@@ -262,15 +263,15 @@ export class PublicClientApplication {
262263
/**
263264
* Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so
264265
* any code that follows this function will not execute.
265-
*
266+
*
266267
* IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current
267268
* browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.
268-
*
269+
*
269270
* @param {@link (AuthenticationParameters:type)}
270271
*/
271272
async loginRedirect(request: AuthorizationUrlRequest): Promise<void> {
272-
// Preflight request
273273
try {
274+
// Preflight request
274275
const validRequest: AuthorizationUrlRequest = this.preflightRequest(request);
275276

276277
// Create auth code request and generate PKCE params
@@ -289,11 +290,11 @@ export class PublicClientApplication {
289290
throw e;
290291
}
291292
}
292-
293+
293294
/**
294295
* Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects
295-
* the page, so any code that follows this function will not execute.
296-
*
296+
* the page, so any code that follows this function will not execute.
297+
*
297298
* IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current
298299
* browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.
299300
* @param {@link (AuthenticationParameters:type)}
@@ -454,18 +455,13 @@ export class PublicClientApplication {
454455
* @param {@link AuthenticationParameters}
455456
*
456457
* To renew idToken, please pass clientId as the only scope in the Authentication Parameters
457-
* @returns {Promise.<TokenResponse>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
458+
* @returns {Promise.<AuthenticationResult>} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object
458459
*
459460
*/
460461
async acquireTokenSilent(silentRequest: SilentFlowRequest): Promise<AuthenticationResult> {
461462
// block the reload if it occurred inside a hidden iframe
462463
BrowserUtils.blockReloadInHiddenIframes();
463464

464-
const tokenRequest: AuthorizationUrlRequest = {
465-
...silentRequest,
466-
redirectUri: "",
467-
};
468-
469465
try {
470466
// Send request to renew token. Auth module will throw errors if token cannot be renewed.
471467
return await this.authModule.getValidToken(silentRequest);
@@ -475,7 +471,8 @@ export class PublicClientApplication {
475471
const isInvalidGrantError = (e.errorCode === BrowserConstants.INVALID_GRANT_ERROR);
476472
if (isServerError && isInvalidGrantError && !isInteractionRequiredError) {
477473
const silentAuthUrlRequest: AuthorizationUrlRequest = this.initializeRequest({
478-
...tokenRequest,
474+
...silentRequest,
475+
redirectUri: "",
479476
prompt: PromptValue.NONE
480477
});
481478

@@ -524,9 +521,13 @@ export class PublicClientApplication {
524521
* Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
525522
* Default behaviour is to redirect the user to `window.location.href`.
526523
*/
527-
logout(accountObj: IAccount): void {
524+
logout(account: IAccount, authorityString?: string): void {
525+
const authorityObj = StringUtils.isEmpty(authorityString) ? this.defaultAuthorityInstance : AuthorityFactory.createInstance(
526+
this.config.auth.authority,
527+
this.config.system.networkClient
528+
);
528529
// create logout string and navigate user window to logout. Auth module will clear cache.
529-
this.authModule.logout(accountObj, this.defaultAuthorityInstance).then((logoutUri: string) => {
530+
this.authModule.logout(account, authorityObj).then((logoutUri: string) => {
530531
BrowserUtils.navigateWindow(logoutUri);
531532
});
532533
}
@@ -557,13 +558,24 @@ export class PublicClientApplication {
557558
}
558559

559560
/**
560-
* Returns the signed in account
561+
* Returns all accounts that MSAL currently has data for.
562+
* (the account object is created at the time of successful login)
563+
* or null when no state is found
564+
* @returns {@link IAccount[]} - Array of account objects in cache
565+
*/
566+
public getAllAccounts(): IAccount[] {
567+
return this.authModule.getAllAccounts();
568+
}
569+
570+
/**
571+
* Returns the signed in account matching username.
561572
* (the account object is created at the time of successful login)
562573
* or null when no state is found
563-
* @returns {@link Account} - the account object stored in MSAL
574+
* @returns {@link IAccount} - the account object stored in MSAL
564575
*/
565-
public getAccount(homeAccountId: string): AccountEntity {
566-
return this.authModule.getAccount(homeAccountId);
576+
public getAccountByUsername(userName: string): IAccount {
577+
const allAccounts = this.getAllAccounts();
578+
return allAccounts.filter(accountObj => accountObj.username === userName)[0];
567579
}
568580

569581
// #endregion
@@ -575,13 +587,13 @@ export class PublicClientApplication {
575587
*/
576588
private interactionInProgress(): boolean {
577589
// Check whether value in cache is present and equal to expected value
578-
return this.browserStorage.getItem(BrowserConstants.INTERACTION_STATUS_KEY) === BrowserConstants.INTERACTION_IN_PROGRESS_VALUE;
590+
return (this.browserStorage.getItem(this.browserStorage.generateCacheKey(BrowserConstants.INTERACTION_STATUS_KEY), CacheSchemaType.TEMPORARY) as string) === BrowserConstants.INTERACTION_IN_PROGRESS_VALUE;
579591
}
580592

581593
/**
582594
* Helper to validate app environment before making a request.
583595
*/
584-
private preflightRequest(request: AuthorizationUrlRequest): AuthorizationUrlRequest {
596+
private preflightRequest(request: AuthorizationUrlRequest): AuthorizationUrlRequest {
585597
// block the reload if it occurred inside a hidden iframe
586598
BrowserUtils.blockReloadInHiddenIframes();
587599

@@ -595,7 +607,7 @@ export class PublicClientApplication {
595607

596608
/**
597609
* Helper to initialize required request parameters.
598-
* @param request
610+
* @param request
599611
*/
600612
private initializeRequest(request: AuthorizationUrlRequest): AuthorizationUrlRequest {
601613
const validatedRequest: AuthorizationUrlRequest = {
@@ -605,7 +617,7 @@ export class PublicClientApplication {
605617
// Check for ADAL SSO
606618
if (StringUtils.isEmpty(validatedRequest.loginHint)) {
607619
// Only check for adal token if no SSO params are being used
608-
const adalIdTokenString = this.browserStorage.getItem(PersistentCacheKeys.ADAL_ID_TOKEN);
620+
const adalIdTokenString = this.browserStorage.getItem(PersistentCacheKeys.ADAL_ID_TOKEN, CacheSchemaType.TEMPORARY) as string;
609621
if (!StringUtils.isEmpty(adalIdTokenString)) {
610622
const adalIdToken = new IdToken(adalIdTokenString, this.browserCrypto);
611623
this.browserStorage.removeItem(PersistentCacheKeys.ADAL_ID_TOKEN);

0 commit comments

Comments
 (0)