@azure/msal-browser 3.28.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/IPublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientNext.mjs +1 -1
- package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +1 -1
- package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
- package/dist/broker/nativeBroker/NativeMessageHandler.mjs +8 -8
- package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +1 -1
- package/dist/broker/nativeBroker/NativeResponse.d.ts +1 -1
- package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
- package/dist/cache/AccountManager.mjs +1 -1
- package/dist/cache/AsyncMemoryStorage.mjs +1 -1
- package/dist/cache/BrowserCacheManager.d.ts +11 -51
- package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
- package/dist/cache/BrowserCacheManager.mjs +42 -291
- package/dist/cache/BrowserCacheManager.mjs.map +1 -1
- package/dist/cache/CacheHelpers.d.ts +16 -0
- package/dist/cache/CacheHelpers.d.ts.map +1 -0
- package/dist/cache/CacheHelpers.mjs +46 -0
- package/dist/cache/CacheHelpers.mjs.map +1 -0
- package/dist/cache/CookieStorage.d.ts +3 -0
- package/dist/cache/CookieStorage.d.ts.map +1 -1
- package/dist/cache/CookieStorage.mjs +12 -1
- package/dist/cache/CookieStorage.mjs.map +1 -1
- package/dist/cache/DatabaseStorage.mjs +1 -1
- package/dist/cache/ITokenCache.d.ts +1 -1
- package/dist/cache/ITokenCache.d.ts.map +1 -1
- package/dist/cache/IWindowStorage.d.ts +12 -0
- package/dist/cache/IWindowStorage.d.ts.map +1 -1
- package/dist/cache/LocalStorage.d.ts +38 -1
- package/dist/cache/LocalStorage.d.ts.map +1 -1
- package/dist/cache/LocalStorage.mjs +183 -2
- package/dist/cache/LocalStorage.mjs.map +1 -1
- package/dist/cache/MemoryStorage.d.ts +3 -0
- package/dist/cache/MemoryStorage.d.ts.map +1 -1
- package/dist/cache/MemoryStorage.mjs +10 -1
- package/dist/cache/MemoryStorage.mjs.map +1 -1
- package/dist/cache/SessionStorage.d.ts +3 -0
- package/dist/cache/SessionStorage.d.ts.map +1 -1
- package/dist/cache/SessionStorage.mjs +10 -1
- package/dist/cache/SessionStorage.mjs.map +1 -1
- package/dist/cache/TokenCache.d.ts +1 -1
- package/dist/cache/TokenCache.d.ts.map +1 -1
- package/dist/cache/TokenCache.mjs +16 -15
- package/dist/cache/TokenCache.mjs.map +1 -1
- package/dist/config/Configuration.d.ts +2 -2
- package/dist/config/Configuration.d.ts.map +1 -1
- package/dist/config/Configuration.mjs +5 -5
- package/dist/config/Configuration.mjs.map +1 -1
- package/dist/controllers/ControllerFactory.mjs +1 -1
- package/dist/controllers/NestedAppAuthController.d.ts +4 -3
- package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
- package/dist/controllers/NestedAppAuthController.mjs +8 -6
- package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
- package/dist/controllers/StandardController.d.ts +2 -2
- package/dist/controllers/StandardController.d.ts.map +1 -1
- package/dist/controllers/StandardController.mjs +27 -22
- package/dist/controllers/StandardController.mjs.map +1 -1
- package/dist/controllers/UnknownOperatingContextController.d.ts +2 -2
- package/dist/controllers/UnknownOperatingContextController.d.ts.map +1 -1
- package/dist/controllers/UnknownOperatingContextController.mjs +3 -3
- package/dist/controllers/UnknownOperatingContextController.mjs.map +1 -1
- package/dist/crypto/BrowserCrypto.d.ts +27 -0
- package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
- package/dist/crypto/BrowserCrypto.mjs +83 -3
- package/dist/crypto/BrowserCrypto.mjs.map +1 -1
- package/dist/crypto/CryptoOps.mjs +1 -1
- package/dist/crypto/PkceGenerator.mjs +1 -1
- package/dist/crypto/SignedHttpRequest.mjs +1 -1
- package/dist/encode/Base64Decode.d.ts +5 -0
- package/dist/encode/Base64Decode.d.ts.map +1 -1
- package/dist/encode/Base64Decode.mjs +2 -2
- package/dist/encode/Base64Decode.mjs.map +1 -1
- package/dist/encode/Base64Encode.mjs +1 -1
- package/dist/error/BrowserAuthError.mjs +1 -1
- package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
- package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
- package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
- package/dist/error/NativeAuthError.mjs +1 -1
- package/dist/error/NativeAuthError.mjs.map +1 -1
- package/dist/error/NativeAuthErrorCodes.mjs +1 -1
- package/dist/error/NestedAppAuthError.mjs +1 -1
- package/dist/event/EventHandler.mjs +1 -1
- package/dist/event/EventMessage.mjs +1 -1
- package/dist/event/EventType.mjs +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
- package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
- package/dist/interaction_client/NativeInteractionClient.d.ts +2 -2
- package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/NativeInteractionClient.mjs +6 -6
- package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
- package/dist/interaction_client/PopupClient.d.ts.map +1 -1
- package/dist/interaction_client/PopupClient.mjs +4 -4
- package/dist/interaction_client/PopupClient.mjs.map +1 -1
- package/dist/interaction_client/RedirectClient.mjs +2 -2
- package/dist/interaction_client/RedirectClient.mjs.map +1 -1
- package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
- package/dist/interaction_client/SilentCacheClient.mjs +1 -1
- package/dist/interaction_client/SilentIframeClient.mjs +2 -2
- package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
- package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
- package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/StandardInteractionClient.mjs +1 -8
- package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
- package/dist/interaction_handler/InteractionHandler.mjs +1 -1
- package/dist/interaction_handler/RedirectHandler.mjs +1 -1
- package/dist/interaction_handler/SilentHandler.mjs +1 -1
- package/dist/naa/BridgeError.mjs +1 -1
- package/dist/naa/BridgeProxy.mjs +1 -1
- package/dist/naa/BridgeStatusCode.mjs +1 -1
- package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
- package/dist/navigation/NavigationClient.mjs +1 -1
- package/dist/network/FetchClient.mjs +1 -1
- package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
- package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
- package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
- package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.d.ts.map +1 -1
- package/dist/packageMetadata.mjs +2 -2
- package/dist/request/AuthorizationUrlRequest.d.ts +1 -1
- package/dist/request/AuthorizationUrlRequest.d.ts.map +1 -1
- package/dist/request/PopupRequest.d.ts +1 -1
- package/dist/request/PopupRequest.d.ts.map +1 -1
- package/dist/request/RedirectRequest.d.ts +1 -1
- package/dist/request/RedirectRequest.d.ts.map +1 -1
- package/dist/request/RequestHelpers.mjs +1 -1
- package/dist/request/SsoSilentRequest.d.ts +1 -1
- package/dist/request/SsoSilentRequest.d.ts.map +1 -1
- package/dist/response/ResponseHandler.mjs +1 -1
- package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
- package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
- package/dist/utils/BrowserConstants.mjs +1 -1
- package/dist/utils/BrowserProtocolUtils.mjs +1 -1
- package/dist/utils/BrowserUtils.mjs +1 -1
- package/lib/msal-browser.cjs +630 -650
- package/lib/msal-browser.cjs.map +1 -1
- package/lib/msal-browser.js +630 -650
- package/lib/msal-browser.js.map +1 -1
- package/lib/msal-browser.min.js +65 -66
- package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts +1 -1
- package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
- package/lib/types/broker/nativeBroker/NativeResponse.d.ts +1 -1
- package/lib/types/cache/BrowserCacheManager.d.ts +11 -51
- package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
- package/lib/types/cache/CacheHelpers.d.ts +16 -0
- package/lib/types/cache/CacheHelpers.d.ts.map +1 -0
- package/lib/types/cache/CookieStorage.d.ts +3 -0
- package/lib/types/cache/CookieStorage.d.ts.map +1 -1
- package/lib/types/cache/ITokenCache.d.ts +1 -1
- package/lib/types/cache/ITokenCache.d.ts.map +1 -1
- package/lib/types/cache/IWindowStorage.d.ts +12 -0
- package/lib/types/cache/IWindowStorage.d.ts.map +1 -1
- package/lib/types/cache/LocalStorage.d.ts +38 -1
- package/lib/types/cache/LocalStorage.d.ts.map +1 -1
- package/lib/types/cache/MemoryStorage.d.ts +3 -0
- package/lib/types/cache/MemoryStorage.d.ts.map +1 -1
- package/lib/types/cache/SessionStorage.d.ts +3 -0
- package/lib/types/cache/SessionStorage.d.ts.map +1 -1
- package/lib/types/cache/TokenCache.d.ts +1 -1
- package/lib/types/cache/TokenCache.d.ts.map +1 -1
- package/lib/types/config/Configuration.d.ts +2 -2
- package/lib/types/config/Configuration.d.ts.map +1 -1
- package/lib/types/controllers/NestedAppAuthController.d.ts +4 -3
- package/lib/types/controllers/NestedAppAuthController.d.ts.map +1 -1
- package/lib/types/controllers/StandardController.d.ts +2 -2
- package/lib/types/controllers/StandardController.d.ts.map +1 -1
- package/lib/types/controllers/UnknownOperatingContextController.d.ts +2 -2
- package/lib/types/controllers/UnknownOperatingContextController.d.ts.map +1 -1
- package/lib/types/crypto/BrowserCrypto.d.ts +27 -0
- package/lib/types/crypto/BrowserCrypto.d.ts.map +1 -1
- package/lib/types/encode/Base64Decode.d.ts +5 -0
- package/lib/types/encode/Base64Decode.d.ts.map +1 -1
- package/lib/types/index.d.ts +0 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/interaction_client/NativeInteractionClient.d.ts +2 -2
- package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +1 -1
- package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
- package/lib/types/interaction_client/StandardInteractionClient.d.ts.map +1 -1
- package/lib/types/packageMetadata.d.ts +1 -1
- package/lib/types/packageMetadata.d.ts.map +1 -1
- package/lib/types/request/AuthorizationUrlRequest.d.ts +1 -1
- package/lib/types/request/AuthorizationUrlRequest.d.ts.map +1 -1
- package/lib/types/request/PopupRequest.d.ts +1 -1
- package/lib/types/request/PopupRequest.d.ts.map +1 -1
- package/lib/types/request/RedirectRequest.d.ts +1 -1
- package/lib/types/request/RedirectRequest.d.ts.map +1 -1
- package/lib/types/request/SsoSilentRequest.d.ts +1 -1
- package/lib/types/request/SsoSilentRequest.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/broker/nativeBroker/NativeMessageHandler.ts +7 -7
- package/src/broker/nativeBroker/NativeResponse.ts +1 -1
- package/src/cache/BrowserCacheManager.ts +95 -422
- package/src/cache/CacheHelpers.ts +52 -0
- package/src/cache/CookieStorage.ts +18 -0
- package/src/cache/ITokenCache.ts +1 -1
- package/src/cache/IWindowStorage.ts +14 -0
- package/src/cache/LocalStorage.ts +330 -1
- package/src/cache/MemoryStorage.ts +12 -0
- package/src/cache/SessionStorage.ts +12 -0
- package/src/cache/TokenCache.ts +42 -25
- package/src/config/Configuration.ts +6 -6
- package/src/controllers/NestedAppAuthController.ts +14 -6
- package/src/controllers/StandardController.ts +41 -22
- package/src/controllers/UnknownOperatingContextController.ts +6 -5
- package/src/crypto/BrowserCrypto.ts +120 -1
- package/src/encode/Base64Decode.ts +1 -1
- package/src/index.ts +0 -1
- package/src/interaction_client/NativeInteractionClient.ts +7 -6
- package/src/interaction_client/PopupClient.ts +9 -8
- package/src/interaction_client/RedirectClient.ts +1 -1
- package/src/interaction_client/SilentIframeClient.ts +1 -1
- package/src/interaction_client/StandardInteractionClient.ts +0 -8
- package/src/packageMetadata.ts +1 -1
- package/src/request/AuthorizationUrlRequest.ts +1 -1
- package/src/request/PopupRequest.ts +1 -1
- package/src/request/RedirectRequest.ts +1 -1
- package/src/request/SsoSilentRequest.ts +1 -1
- package/dist/cache/BrowserStorage.d.ts +0 -14
- package/dist/cache/BrowserStorage.d.ts.map +0 -1
- package/dist/cache/BrowserStorage.mjs +0 -46
- package/dist/cache/BrowserStorage.mjs.map +0 -1
- package/lib/types/cache/BrowserStorage.d.ts +0 -14
- package/lib/types/cache/BrowserStorage.d.ts.map +0 -1
- package/src/cache/BrowserStorage.ts +0 -52
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TokenKeys } from "@azure/msal-common/browser";
|
|
7
|
+
import { StaticCacheKeys } from "../utils/BrowserConstants.js";
|
|
8
|
+
import { IWindowStorage } from "./IWindowStorage.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns a list of cache keys for all known accounts
|
|
12
|
+
* @param storage
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
export function getAccountKeys(storage: IWindowStorage<string>): Array<string> {
|
|
16
|
+
const accountKeys = storage.getItem(StaticCacheKeys.ACCOUNT_KEYS);
|
|
17
|
+
if (accountKeys) {
|
|
18
|
+
return JSON.parse(accountKeys);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns a list of cache keys for all known tokens
|
|
26
|
+
* @param clientId
|
|
27
|
+
* @param storage
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
export function getTokenKeys(
|
|
31
|
+
clientId: string,
|
|
32
|
+
storage: IWindowStorage<string>
|
|
33
|
+
): TokenKeys {
|
|
34
|
+
const item = storage.getItem(`${StaticCacheKeys.TOKEN_KEYS}.${clientId}`);
|
|
35
|
+
if (item) {
|
|
36
|
+
const tokenKeys = JSON.parse(item);
|
|
37
|
+
if (
|
|
38
|
+
tokenKeys &&
|
|
39
|
+
tokenKeys.hasOwnProperty("idToken") &&
|
|
40
|
+
tokenKeys.hasOwnProperty("accessToken") &&
|
|
41
|
+
tokenKeys.hasOwnProperty("refreshToken")
|
|
42
|
+
) {
|
|
43
|
+
return tokenKeys as TokenKeys;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
idToken: [],
|
|
49
|
+
accessToken: [],
|
|
50
|
+
refreshToken: [],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -3,12 +3,20 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
ClientAuthErrorCodes,
|
|
8
|
+
createClientAuthError,
|
|
9
|
+
} from "@azure/msal-common/browser";
|
|
6
10
|
import { IWindowStorage } from "./IWindowStorage.js";
|
|
7
11
|
|
|
8
12
|
// Cookie life calculation (hours * minutes * seconds * ms)
|
|
9
13
|
const COOKIE_LIFE_MULTIPLIER = 24 * 60 * 60 * 1000;
|
|
10
14
|
|
|
11
15
|
export class CookieStorage implements IWindowStorage<string> {
|
|
16
|
+
initialize(): Promise<void> {
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
getItem(key: string): string | null {
|
|
13
21
|
const name = `${encodeURIComponent(key)}`;
|
|
14
22
|
const cookieList = document.cookie.split(";");
|
|
@@ -24,6 +32,10 @@ export class CookieStorage implements IWindowStorage<string> {
|
|
|
24
32
|
return "";
|
|
25
33
|
}
|
|
26
34
|
|
|
35
|
+
getUserData(): string | null {
|
|
36
|
+
throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
setItem(
|
|
28
40
|
key: string,
|
|
29
41
|
value: string,
|
|
@@ -46,6 +58,12 @@ export class CookieStorage implements IWindowStorage<string> {
|
|
|
46
58
|
document.cookie = cookieStr;
|
|
47
59
|
}
|
|
48
60
|
|
|
61
|
+
async setUserData(): Promise<void> {
|
|
62
|
+
return Promise.reject(
|
|
63
|
+
createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
49
67
|
removeItem(key: string): void {
|
|
50
68
|
// Setting expiration to -1 removes it
|
|
51
69
|
this.setItem(key, "", -1);
|
package/src/cache/ITokenCache.ts
CHANGED
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export interface IWindowStorage<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Async initializer
|
|
9
|
+
*/
|
|
10
|
+
initialize(correlationId: string): Promise<void>;
|
|
7
11
|
/**
|
|
8
12
|
* Get the item from the window storage object matching the given key.
|
|
9
13
|
* @param key
|
|
10
14
|
*/
|
|
11
15
|
getItem(key: string): T | null;
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Getter for sensitive data that may contain PII.
|
|
19
|
+
*/
|
|
20
|
+
getUserData(key: string): T | null;
|
|
21
|
+
|
|
13
22
|
/**
|
|
14
23
|
* Sets the item in the window storage object with the given key.
|
|
15
24
|
* @param key
|
|
@@ -17,6 +26,11 @@ export interface IWindowStorage<T> {
|
|
|
17
26
|
*/
|
|
18
27
|
setItem(key: string, value: T): void;
|
|
19
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Setter for sensitive data that may contain PII.
|
|
31
|
+
*/
|
|
32
|
+
setUserData(key: string, value: T, correlationId: string): Promise<void>;
|
|
33
|
+
|
|
20
34
|
/**
|
|
21
35
|
* Removes the item in the window storage object matching the given key.
|
|
22
36
|
* @param key
|
|
@@ -3,30 +3,197 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
Constants,
|
|
8
|
+
TokenKeys,
|
|
9
|
+
IPerformanceClient,
|
|
10
|
+
invokeAsync,
|
|
11
|
+
PerformanceEvents,
|
|
12
|
+
Logger,
|
|
13
|
+
invoke,
|
|
14
|
+
} from "@azure/msal-common/browser";
|
|
15
|
+
import {
|
|
16
|
+
createNewGuid,
|
|
17
|
+
decrypt,
|
|
18
|
+
encrypt,
|
|
19
|
+
generateBaseKey,
|
|
20
|
+
generateHKDF,
|
|
21
|
+
} from "../crypto/BrowserCrypto.js";
|
|
22
|
+
import { base64DecToArr } from "../encode/Base64Decode.js";
|
|
23
|
+
import { urlEncodeArr } from "../encode/Base64Encode.js";
|
|
24
|
+
import {
|
|
25
|
+
BrowserAuthErrorCodes,
|
|
26
|
+
createBrowserAuthError,
|
|
27
|
+
} from "../error/BrowserAuthError.js";
|
|
6
28
|
import {
|
|
7
29
|
BrowserConfigurationAuthErrorCodes,
|
|
8
30
|
createBrowserConfigurationAuthError,
|
|
9
31
|
} from "../error/BrowserConfigurationAuthError.js";
|
|
32
|
+
import { CookieStorage } from "./CookieStorage.js";
|
|
10
33
|
import { IWindowStorage } from "./IWindowStorage.js";
|
|
34
|
+
import { MemoryStorage } from "./MemoryStorage.js";
|
|
35
|
+
import { getAccountKeys, getTokenKeys } from "./CacheHelpers.js";
|
|
36
|
+
import { StaticCacheKeys } from "../utils/BrowserConstants.js";
|
|
37
|
+
|
|
38
|
+
const ENCRYPTION_KEY = "msal.cache.encryption";
|
|
39
|
+
|
|
40
|
+
type EncryptionCookie = {
|
|
41
|
+
id: string;
|
|
42
|
+
key: CryptoKey;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type EncryptedData = {
|
|
46
|
+
id: string;
|
|
47
|
+
nonce: string;
|
|
48
|
+
data: string;
|
|
49
|
+
};
|
|
11
50
|
|
|
12
51
|
export class LocalStorage implements IWindowStorage<string> {
|
|
13
|
-
|
|
52
|
+
private clientId: string;
|
|
53
|
+
private initialized: boolean;
|
|
54
|
+
private memoryStorage: MemoryStorage<string>;
|
|
55
|
+
private performanceClient: IPerformanceClient;
|
|
56
|
+
private logger: Logger;
|
|
57
|
+
private encryptionCookie?: EncryptionCookie;
|
|
58
|
+
|
|
59
|
+
constructor(
|
|
60
|
+
clientId: string,
|
|
61
|
+
logger: Logger,
|
|
62
|
+
performanceClient: IPerformanceClient
|
|
63
|
+
) {
|
|
14
64
|
if (!window.localStorage) {
|
|
15
65
|
throw createBrowserConfigurationAuthError(
|
|
16
66
|
BrowserConfigurationAuthErrorCodes.storageNotSupported
|
|
17
67
|
);
|
|
18
68
|
}
|
|
69
|
+
this.memoryStorage = new MemoryStorage<string>();
|
|
70
|
+
this.initialized = false;
|
|
71
|
+
this.clientId = clientId;
|
|
72
|
+
this.logger = logger;
|
|
73
|
+
this.performanceClient = performanceClient;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async initialize(correlationId: string): Promise<void> {
|
|
77
|
+
this.initialized = true;
|
|
78
|
+
|
|
79
|
+
const cookies = new CookieStorage();
|
|
80
|
+
const cookieString = cookies.getItem(ENCRYPTION_KEY);
|
|
81
|
+
let parsedCookie = { key: "", id: "" };
|
|
82
|
+
if (cookieString) {
|
|
83
|
+
try {
|
|
84
|
+
parsedCookie = JSON.parse(cookieString);
|
|
85
|
+
} catch (e) {}
|
|
86
|
+
}
|
|
87
|
+
if (parsedCookie.key && parsedCookie.id) {
|
|
88
|
+
// Encryption key already exists, import
|
|
89
|
+
const baseKey = invoke(
|
|
90
|
+
base64DecToArr,
|
|
91
|
+
PerformanceEvents.Base64Decode,
|
|
92
|
+
this.logger,
|
|
93
|
+
this.performanceClient,
|
|
94
|
+
correlationId
|
|
95
|
+
)(parsedCookie.key);
|
|
96
|
+
this.encryptionCookie = {
|
|
97
|
+
id: parsedCookie.id,
|
|
98
|
+
key: await invokeAsync(
|
|
99
|
+
generateHKDF,
|
|
100
|
+
PerformanceEvents.GenerateHKDF,
|
|
101
|
+
this.logger,
|
|
102
|
+
this.performanceClient,
|
|
103
|
+
correlationId
|
|
104
|
+
)(baseKey),
|
|
105
|
+
};
|
|
106
|
+
await invokeAsync(
|
|
107
|
+
this.importExistingCache.bind(this),
|
|
108
|
+
PerformanceEvents.ImportExistingCache,
|
|
109
|
+
this.logger,
|
|
110
|
+
this.performanceClient,
|
|
111
|
+
correlationId
|
|
112
|
+
)(correlationId);
|
|
113
|
+
} else {
|
|
114
|
+
// Encryption key doesn't exist or is invalid, generate a new one and clear existing cache
|
|
115
|
+
this.clear();
|
|
116
|
+
const id = createNewGuid();
|
|
117
|
+
const baseKey = await invokeAsync(
|
|
118
|
+
generateBaseKey,
|
|
119
|
+
PerformanceEvents.GenerateBaseKey,
|
|
120
|
+
this.logger,
|
|
121
|
+
this.performanceClient,
|
|
122
|
+
correlationId
|
|
123
|
+
)();
|
|
124
|
+
const keyStr = invoke(
|
|
125
|
+
urlEncodeArr,
|
|
126
|
+
PerformanceEvents.UrlEncodeArr,
|
|
127
|
+
this.logger,
|
|
128
|
+
this.performanceClient,
|
|
129
|
+
correlationId
|
|
130
|
+
)(new Uint8Array(baseKey));
|
|
131
|
+
this.encryptionCookie = {
|
|
132
|
+
id: id,
|
|
133
|
+
key: await invokeAsync(
|
|
134
|
+
generateHKDF,
|
|
135
|
+
PerformanceEvents.GenerateHKDF,
|
|
136
|
+
this.logger,
|
|
137
|
+
this.performanceClient,
|
|
138
|
+
correlationId
|
|
139
|
+
)(baseKey),
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const cookieData = {
|
|
143
|
+
id: id,
|
|
144
|
+
key: keyStr,
|
|
145
|
+
};
|
|
146
|
+
cookies.setItem(ENCRYPTION_KEY, JSON.stringify(cookieData));
|
|
147
|
+
}
|
|
19
148
|
}
|
|
20
149
|
|
|
21
150
|
getItem(key: string): string | null {
|
|
22
151
|
return window.localStorage.getItem(key);
|
|
23
152
|
}
|
|
24
153
|
|
|
154
|
+
getUserData(key: string): string | null {
|
|
155
|
+
if (!this.initialized) {
|
|
156
|
+
throw createBrowserAuthError(
|
|
157
|
+
BrowserAuthErrorCodes.uninitializedPublicClientApplication
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return this.memoryStorage.getItem(key);
|
|
161
|
+
}
|
|
162
|
+
|
|
25
163
|
setItem(key: string, value: string): void {
|
|
26
164
|
window.localStorage.setItem(key, value);
|
|
27
165
|
}
|
|
28
166
|
|
|
167
|
+
async setUserData(
|
|
168
|
+
key: string,
|
|
169
|
+
value: string,
|
|
170
|
+
correlationId: string
|
|
171
|
+
): Promise<void> {
|
|
172
|
+
if (!this.initialized || !this.encryptionCookie) {
|
|
173
|
+
throw createBrowserAuthError(
|
|
174
|
+
BrowserAuthErrorCodes.uninitializedPublicClientApplication
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const { data, nonce } = await invokeAsync(
|
|
179
|
+
encrypt,
|
|
180
|
+
PerformanceEvents.Encrypt,
|
|
181
|
+
this.logger,
|
|
182
|
+
this.performanceClient,
|
|
183
|
+
correlationId
|
|
184
|
+
)(this.encryptionCookie.key, value, this.getContext(key));
|
|
185
|
+
const encryptedData: EncryptedData = {
|
|
186
|
+
id: this.encryptionCookie.id,
|
|
187
|
+
nonce: nonce,
|
|
188
|
+
data: data,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
this.memoryStorage.setItem(key, value);
|
|
192
|
+
this.setItem(key, JSON.stringify(encryptedData));
|
|
193
|
+
}
|
|
194
|
+
|
|
29
195
|
removeItem(key: string): void {
|
|
196
|
+
this.memoryStorage.removeItem(key);
|
|
30
197
|
window.localStorage.removeItem(key);
|
|
31
198
|
}
|
|
32
199
|
|
|
@@ -37,4 +204,166 @@ export class LocalStorage implements IWindowStorage<string> {
|
|
|
37
204
|
containsKey(key: string): boolean {
|
|
38
205
|
return window.localStorage.hasOwnProperty(key);
|
|
39
206
|
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Removes all known MSAL keys from the cache
|
|
210
|
+
*/
|
|
211
|
+
clear(): void {
|
|
212
|
+
// Removes all remaining MSAL cache items
|
|
213
|
+
this.memoryStorage.clear();
|
|
214
|
+
|
|
215
|
+
const accountKeys = getAccountKeys(this);
|
|
216
|
+
accountKeys.forEach((key) => this.removeItem(key));
|
|
217
|
+
const tokenKeys = getTokenKeys(this.clientId, this);
|
|
218
|
+
tokenKeys.idToken.forEach((key) => this.removeItem(key));
|
|
219
|
+
tokenKeys.accessToken.forEach((key) => this.removeItem(key));
|
|
220
|
+
tokenKeys.refreshToken.forEach((key) => this.removeItem(key));
|
|
221
|
+
|
|
222
|
+
// Clean up anything left
|
|
223
|
+
this.getKeys().forEach((cacheKey: string) => {
|
|
224
|
+
if (
|
|
225
|
+
cacheKey.startsWith(Constants.CACHE_PREFIX) ||
|
|
226
|
+
cacheKey.indexOf(this.clientId) !== -1
|
|
227
|
+
) {
|
|
228
|
+
this.removeItem(cacheKey);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Helper to decrypt all known MSAL keys in localStorage and save them to inMemory storage
|
|
235
|
+
* @returns
|
|
236
|
+
*/
|
|
237
|
+
private async importExistingCache(correlationId: string): Promise<void> {
|
|
238
|
+
if (!this.encryptionCookie) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
let accountKeys = getAccountKeys(this);
|
|
243
|
+
accountKeys = await this.importArray(accountKeys, correlationId);
|
|
244
|
+
// Write valid account keys back to map
|
|
245
|
+
this.setItem(StaticCacheKeys.ACCOUNT_KEYS, JSON.stringify(accountKeys));
|
|
246
|
+
|
|
247
|
+
const tokenKeys: TokenKeys = getTokenKeys(this.clientId, this);
|
|
248
|
+
tokenKeys.idToken = await this.importArray(
|
|
249
|
+
tokenKeys.idToken,
|
|
250
|
+
correlationId
|
|
251
|
+
);
|
|
252
|
+
tokenKeys.accessToken = await this.importArray(
|
|
253
|
+
tokenKeys.accessToken,
|
|
254
|
+
correlationId
|
|
255
|
+
);
|
|
256
|
+
tokenKeys.refreshToken = await this.importArray(
|
|
257
|
+
tokenKeys.refreshToken,
|
|
258
|
+
correlationId
|
|
259
|
+
);
|
|
260
|
+
// Write valid token keys back to map
|
|
261
|
+
this.setItem(
|
|
262
|
+
`${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`,
|
|
263
|
+
JSON.stringify(tokenKeys)
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Helper to decrypt and save cache entries
|
|
269
|
+
* @param key
|
|
270
|
+
* @returns
|
|
271
|
+
*/
|
|
272
|
+
private async getItemFromEncryptedCache(
|
|
273
|
+
key: string,
|
|
274
|
+
correlationId: string
|
|
275
|
+
): Promise<string | null> {
|
|
276
|
+
if (!this.encryptionCookie) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const rawCache = this.getItem(key);
|
|
281
|
+
if (!rawCache) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let encObj: EncryptedData;
|
|
286
|
+
try {
|
|
287
|
+
encObj = JSON.parse(rawCache);
|
|
288
|
+
} catch (e) {
|
|
289
|
+
// Not a valid encrypted object, remove
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!encObj.id || !encObj.nonce || !encObj.data) {
|
|
294
|
+
// Data is not encrypted, likely from old version of MSAL. It must be removed because we don't know how old it is.
|
|
295
|
+
this.performanceClient.incrementFields(
|
|
296
|
+
{ unencryptedCacheCount: 1 },
|
|
297
|
+
correlationId
|
|
298
|
+
);
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (encObj.id !== this.encryptionCookie.id) {
|
|
303
|
+
// Data was encrypted with a different key. It must be removed because it is from a previous session.
|
|
304
|
+
this.performanceClient.incrementFields(
|
|
305
|
+
{ encryptedCacheExpiredCount: 1 },
|
|
306
|
+
correlationId
|
|
307
|
+
);
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return invokeAsync(
|
|
312
|
+
decrypt,
|
|
313
|
+
PerformanceEvents.Decrypt,
|
|
314
|
+
this.logger,
|
|
315
|
+
this.performanceClient,
|
|
316
|
+
correlationId
|
|
317
|
+
)(
|
|
318
|
+
this.encryptionCookie.key,
|
|
319
|
+
encObj.nonce,
|
|
320
|
+
this.getContext(key),
|
|
321
|
+
encObj.data
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Helper to decrypt and save an array of cache keys
|
|
327
|
+
* @param arr
|
|
328
|
+
* @returns Array of keys successfully imported
|
|
329
|
+
*/
|
|
330
|
+
private async importArray(
|
|
331
|
+
arr: Array<string>,
|
|
332
|
+
correlationId: string
|
|
333
|
+
): Promise<Array<string>> {
|
|
334
|
+
const importedArr: Array<string> = [];
|
|
335
|
+
const promiseArr: Array<Promise<void>> = [];
|
|
336
|
+
arr.forEach((key) => {
|
|
337
|
+
const promise = this.getItemFromEncryptedCache(
|
|
338
|
+
key,
|
|
339
|
+
correlationId
|
|
340
|
+
).then((value) => {
|
|
341
|
+
if (value) {
|
|
342
|
+
this.memoryStorage.setItem(key, value);
|
|
343
|
+
importedArr.push(key);
|
|
344
|
+
} else {
|
|
345
|
+
// If value is empty, unencrypted or expired remove
|
|
346
|
+
this.removeItem(key);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
promiseArr.push(promise);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
await Promise.all(promiseArr);
|
|
353
|
+
return importedArr;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Gets encryption context for a given cache entry. This is clientId for app specific entries, empty string for shared entries
|
|
358
|
+
* @param key
|
|
359
|
+
* @returns
|
|
360
|
+
*/
|
|
361
|
+
private getContext(key: string): string {
|
|
362
|
+
let context = "";
|
|
363
|
+
if (key.includes(this.clientId)) {
|
|
364
|
+
context = this.clientId; // Used to bind encryption key to this appId
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return context;
|
|
368
|
+
}
|
|
40
369
|
}
|
|
@@ -12,14 +12,26 @@ export class MemoryStorage<T> implements IWindowStorage<T> {
|
|
|
12
12
|
this.cache = new Map<string, T>();
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
async initialize(): Promise<void> {
|
|
16
|
+
// Memory storage does not require initialization
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
getItem(key: string): T | null {
|
|
16
20
|
return this.cache.get(key) || null;
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
getUserData(key: string): T | null {
|
|
24
|
+
return this.getItem(key);
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
setItem(key: string, value: T): void {
|
|
20
28
|
this.cache.set(key, value);
|
|
21
29
|
}
|
|
22
30
|
|
|
31
|
+
async setUserData(key: string, value: T): Promise<void> {
|
|
32
|
+
this.setItem(key, value);
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
removeItem(key: string): void {
|
|
24
36
|
this.cache.delete(key);
|
|
25
37
|
}
|
|
@@ -18,14 +18,26 @@ export class SessionStorage implements IWindowStorage<string> {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
async initialize(): Promise<void> {
|
|
22
|
+
// Session storage does not require initialization
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
getItem(key: string): string | null {
|
|
22
26
|
return window.sessionStorage.getItem(key);
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
getUserData(key: string): string | null {
|
|
30
|
+
return this.getItem(key);
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
setItem(key: string, value: string): void {
|
|
26
34
|
window.sessionStorage.setItem(key, value);
|
|
27
35
|
}
|
|
28
36
|
|
|
37
|
+
async setUserData(key: string, value: string): Promise<void> {
|
|
38
|
+
this.setItem(key, value);
|
|
39
|
+
}
|
|
40
|
+
|
|
29
41
|
removeItem(key: string): void {
|
|
30
42
|
window.sessionStorage.removeItem(key);
|
|
31
43
|
}
|