this.logger.error("Could not access persistent storage. This may be caused by browser privacy features which block persistent storage in third-party contexts.");
}
else{
throwerror;
}
};
/**
* Get the item matching the given key. Tries in-memory cache first, then in the asynchronous
{"version":3,"file":"AsyncMemoryStorage.js","sources":["../../src/cache/AsyncMemoryStorage.ts"],"sourcesContent":["/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common\";\nimport { BrowserAuthError, BrowserAuthErrorMessage } from \"../error/BrowserAuthError\";\nimport { DatabaseStorage } from \"./DatabaseStorage\";\nimport { IAsyncStorage } from \"./IAsyncMemoryStorage\";\nimport { MemoryStorage } from \"./MemoryStorage\";\n\n/**\n * This class allows MSAL to store artifacts asynchronously using the DatabaseStorage IndexedDB wrapper,\n * backed up with the more volatile MemoryStorage object for cases in which IndexedDB may be unavailable.\n */\nexport class AsyncMemoryStorage<T> implements IAsyncStorage<T> {\n private inMemoryCache: MemoryStorage<T>;\n private indexedDBCache: DatabaseStorage<T>;\n private logger: Logger;\n private storeName: string;\n\n constructor(logger: Logger, storeName: string) {\n this.inMemoryCache = new MemoryStorage<T>();\n this.indexedDBCache = new DatabaseStorage<T>();\n this.logger = logger;\n this.storeName = storeName;\n }\n\n private handleDatabaseAccessError(error: unknown): void {\n if (error instanceof BrowserAuthError && error.errorCode === BrowserAuthErrorMessage.databaseUnavailable.code) {\n this.logger.error(\"Could not access persistent storage. This may be caused by browser privacy features which block persistent storage in third-party contexts.\");\n } else {\n throw error;\n }\n }\n /**\n * Get the item matching the given key. Tries in-memory cache first, then in the asynchronous\n * storage object if item isn't found in-memory.\n * @param key \n */\n async getItem(key: string): Promise<T | null> {\n const item = this.inMemoryCache.getItem(key);\n if(!item) {\n try {\n this.logger.verbose(\"Queried item not found in in-memory cache, now querying persistent storage.\");\n return await this.indexedDBCache.getItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return item;\n }\n\n /**\n * Sets the item in the in-memory cache and then tries to set it in the asynchronous\n * storage object with the given key.\n * @param key \n * @param value \n */\n async setItem(key: string, value: T): Promise<void> {\n this.inMemoryCache.setItem(key, value);\n try {\n await this.indexedDBCache.setItem(key, value);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Removes the item matching the key from the in-memory cache, then tries to remove it from the asynchronous storage object.\n * @param key \n */\n async removeItem(key: string): Promise<void> {\n this.inMemoryCache.removeItem(key);\n try {\n await this.indexedDBCache.removeItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Get all the keys from the in-memory cache as an iterable array of strings. If no keys are found, query the keys in the \n * asynchronous storage object.\n */\n async getKeys(): Promise<string[]> {\n const cacheKeys = this.inMemoryCache.getKeys();\n if (cacheKeys.length === 0) {\n try {\n this.logger.verbose(\"In-memory cache is empty, now querying persistent storage.\");\n return await this.indexedDBCache.getKeys();\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return cacheKeys;\n }\n\n /**\n * Returns true or false if the given key is present in the cache.\n * @param key \n */\n async containsKey(key: string): Promise<boolean> {\n const containsKey = this.inMemoryCache.containsKey(key);\n if(!containsKey) {\n try {\n this.logger.verbose(\"Key not found in in-memory cache, now querying persistent storage.\");\n return await this.indexedDBCache.containsKey(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return containsKey;\n }\n\n /**\n * Clears in-memory Map\n */\n clearInMemory(): void {\n // InMemory cache is a Map instance, clear is straightforward\n this.logger.verbose(`Deleting in-memory keystore ${this.storeName}`);\n this.inMemoryCache.clear();\n this.logger.verbose(`In-memory keystore ${this.storeName} deleted`);\n }\n\n /**\n * Tries to delete the IndexedDB database\n * @returns\n */\n async clearPersistent(): Promise<boolean> {\n try {\n this.logger.verbose(\"Deleting persistent keystore\");\n const dbDeleted = await this.indexedDBCache.deleteDatabase();\n if (dbDeleted) {\n this.logger.verbose(\"Persistent keystore deleted\");\n }\n \n return dbDeleted;\n } catch (e) {\n this.handleDatabaseAccessError(e);\n return false;\n }\n }\n}\n"],"names":[],"mappings":";;;;;;;AAAA;;;;AAWA;;;;;IAUI,4BAAY,MAAc,EAAE,SAAiB;QACzC,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,EAAK,CAAC;QAC5C,IAAI,CAAC,cAAc,GAAG,IAAI,eAAe,EAAK,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;KAC9B;IAEO,sDAAyB,GAAjC,UAAkC,KAAc;QAC5C,IAAI,KAAK,YAAY,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,uBAAuB,CAAC,mBAAmB,CAAC,IAAI,EAAE;YAC3G,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6IAA6I,CAAC,CAAC;SACpK;aAAM;YACH,MAAM,KAAK,CAAC;SACf;KACJ;;;;;;IAMK,oCAAO,GAAb,UAAc,GAAW;;;;;;wBACf,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;6BAC1C,CAAC,IAAI,EAAL,wBAAK;;;;wBAEA,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,6EAA6E,CAAC,CAAC;wBAC5F,qBAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,EAAA;4BAA7C,sBAAO,SAAsC,EAAC;;;wBAE9C,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;;4BAG1C,sBAAO,IAAI,EAAC;;;;KACf;;;;;;;IAQK,oCAAO,GAAb,UAAc,GAAW,EAAE,KAAQ;;;;;;wBAC/B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;;;;wBAEnC,qBAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,EAAA;;wBAA7C,SAA6C,CAAC;;;;wBAE9C,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;;;;;;KAEzC;;;;;IAMK,uCAAU,GAAhB,UAAiB,GAAW;;;;;;wBACxB,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;;;;wBAE/B,qBAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,EAAA;;wBAAzC,SAAyC,CAAC;;;;wBAE1C,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;;;;;;KAEzC;;;;;IAMK,oCAAO,GAAb;;;;;;wBACU,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;8BAC3C,SAAS,CAAC,MAAM,KAAK,CAAC,CAAA,EAAtB,wBAAsB;;;;wBAElB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,4DAA4D,CAAC,CAAC;wBAC3E,qBAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAA;4BAA1C,sBAAO,SAAmC,EAAC;;;wBAE3C,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;;4BAG1C,sBAAO,SAAS,EAAC;;;;KACpB;;;;;IAMK,wCAAW,GAAjB,UAAkB,GAAW;;;;;;wBACnB,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;6BACrD,CAAC,WAAW,EAAZ,wBAAY;;;;wBAEP,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oEAAoE,CAAC,CAAC;wBACnF,qBAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC,EAAA;4BAAjD,sBAAO,SAA0C,EAAC;;;wBAElD,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;;4BAG1C,sBAAO,WAAW,EAAC;;;;KACtB;;;;IAKD,0CAAa,GAAb;;QAEI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,iCAA+B,IAAI,CAAC,SAAW,CAAC,CAAC;QACrE,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,wBAAsB,IAAI,CAAC,SAAS,aAAU,CAAC,CAAC;KACvE;;;;;IAMK,4CAAe,GAArB;;;;;;;wBAEQ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;wBAClC,qBAAM,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,EAAA;;wBAAtD,SAAS,GAAG,SAA0C;wBAC5D,IAAI,SAAS,EAAE;4BACX,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;yBACtD;wBAED,sBAAO,SAAS,EAAC;;;wBAEjB,IAAI,CAAC,yBAAyB,CAAC,GAAC,CAAC,CAAC;wBAClC,sBAAO,KAAK,EAAC;;;;;KAEpB;IACL,yBAAC;AAAD,CAAC;;;;"}
* interface compat, we cannot overwrite browser cache; Functionality is supported by individual entities in browser
*/
setCache():void;
/**
* Prepend msal.<client-id> to each key; Skip for any JSON object as Key (defined schemas do not need the key appended: AccessToken Keys or the upcoming schema)
* @param key
* @param addInstanceId
*/
generateCacheKey(key:string):string;
/**
* Create authorityKey to cache authority
* @param state
*/
generateAuthorityKey(stateString:string):string;
/**
* Create Nonce key to cache nonce
* @param state
*/
generateNonceKey(stateString:string):string;
/**
* Creates full cache key for the request state
* @param stateString State string for the request
*/
generateStateKey(stateString:string):string;
/**
* Gets the cached authority based on the cached state. Returns empty if no cached state found.
* Prepend msal.<client-id> to each key; Skip for any JSON object as Key (defined schemas do not need the key appended: AccessToken Keys or the upcoming schema)
this.logger.verbose("No SSO params used and ADAL/MSAL v1 token retrieved, setting ADAL/MSAL v1 upn as loginHint");
returncachedIdToken.claims.upn;
}
else{
this.logger.verbose("No SSO params used and ADAL/MSAL v1 token retrieved, however, no account hint claim found. Enable preferred_username or upn id token claim to get SSO.");
}
}
returnnull;
};
/**
* Updates a credential's cache key if the current cache key is outdated
this.logger.verbose("Updated an outdated "+credential.credentialType+" cache key");
returnupdatedCacheKey;
}
else{
this.logger.error("Attempted to update an outdated "+credential.credentialType+" cache key but no item matching the outdated key was found in storage");
}
}
returncurrentCacheKey;
};
/**
* Returns application id as redirect context during AcquireTokenRedirect flow.
{"version":3,"file":"CryptoKeyStore.js","sources":["../../src/cache/CryptoKeyStore.ts"],"sourcesContent":["/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common\";\nimport { CachedKeyPair } from \"../crypto/CryptoOps\";\nimport { AsyncMemoryStorage } from \"./AsyncMemoryStorage\";\n\nexport enum CryptoKeyStoreNames {\n asymmetricKeys = \"asymmetricKeys\",\n symmetricKeys = \"symmetricKeys\"\n}\n/**\n * MSAL CryptoKeyStore DB Version 2\n */\nexport class CryptoKeyStore {\n public asymmetricKeys: AsyncMemoryStorage<CachedKeyPair>;\n public symmetricKeys: AsyncMemoryStorage<CryptoKey>;\n public logger: Logger;\n\n constructor(logger: Logger){\n this.logger = logger;\n this.asymmetricKeys = new AsyncMemoryStorage<CachedKeyPair>(this.logger, CryptoKeyStoreNames.asymmetricKeys);\n this.symmetricKeys = new AsyncMemoryStorage<CryptoKey>(this.logger, CryptoKeyStoreNames.symmetricKeys);\n }\n\n async clear(): Promise<boolean> {\n // Delete in-memory keystores\n this.asymmetricKeys.clearInMemory();\n\t this.symmetricKeys.clearInMemory();\n\t\t\n /**\n * There is only one database, so calling clearPersistent on asymmetric keystore takes care of\n * every persistent keystore\n */\n try {\n await this.asymmetricKeys.clearPersistent();\n return true;\n } catch (e) {\n if (e instanceof Error) {\n this.logger.error(`Clearing keystore failed with error: ${e.message}`);\n } else {\n this.logger.error(\"Clearing keystore failed with unknown error\");\n }\n \n return false;\n }\n }\n}\n"],"names":[],"mappings":";;;;;AAAA;;;;IASY;AAAZ,WAAY,mBAAmB;IAC3B,wDAAiC,CAAA;IACjC,sDAA+B,CAAA;AACnC,CAAC,EAHW,mBAAmB,KAAnB,mBAAmB,QAG9B;AACD;;;;IAQI,wBAAY,MAAc;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,IAAI,kBAAkB,CAAgB,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,cAAc,CAAC,CAAC;QAC7G,IAAI,CAAC,aAAa,GAAG,IAAI,kBAAkB,CAAY,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAC;KAC1G;IAEK,8BAAK,GAAX;;;;;;;wBAEI,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC;wBACvC,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;;;;wBAO5B,qBAAM,IAAI,CAAC,cAAc,CAAC,eAAe,EAAE,EAAA;;wBAA3C,SAA2C,CAAC;wBAC5C,sBAAO,IAAI,EAAC;;;wBAEZ,IAAI,GAAC,YAAY,KAAK,EAAE;4BACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0CAAwC,GAAC,CAAC,OAAS,CAAC,CAAC;yBAC1E;6BAAM;4BACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;yBACpE;wBAED,sBAAO,KAAK,EAAC;;;;;KAEpB;IACL,qBAAC;AAAD,CAAC;;;;"}