diff --git a/change/@azure-msal-browser-f7a90af8-1831-4893-aaff-47bd8fc53621.json b/change/@azure-msal-browser-f7a90af8-1831-4893-aaff-47bd8fc53621.json new file mode 100644 index 0000000000..5c791f6dc9 --- /dev/null +++ b/change/@azure-msal-browser-f7a90af8-1831-4893-aaff-47bd8fc53621.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Refactor token cache entities to be defined as Types rather than Classes #6580", + "packageName": "@azure/msal-browser", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-msal-common-3221a6c8-6fb8-41ed-8eb8-7ee31f61f10d.json b/change/@azure-msal-common-3221a6c8-6fb8-41ed-8eb8-7ee31f61f10d.json new file mode 100644 index 0000000000..ad6d70b997 --- /dev/null +++ b/change/@azure-msal-common-3221a6c8-6fb8-41ed-8eb8-7ee31f61f10d.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Refactor token cache entities to be defined as Types rather than Classes #6580", + "packageName": "@azure/msal-common", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-msal-node-14ef94d7-7234-47c0-9875-b3bb2caf75d7.json b/change/@azure-msal-node-14ef94d7-7234-47c0-9875-b3bb2caf75d7.json new file mode 100644 index 0000000000..90bd4e05e1 --- /dev/null +++ b/change/@azure-msal-node-14ef94d7-7234-47c0-9875-b3bb2caf75d7.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Refactor token cache entities to be defined as Types rather than Classes #6580", + "packageName": "@azure/msal-node", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/lib/msal-browser/src/cache/BrowserCacheManager.ts b/lib/msal-browser/src/cache/BrowserCacheManager.ts index fafae59400..1722c3d787 100644 --- a/lib/msal-browser/src/cache/BrowserCacheManager.ts +++ b/lib/msal-browser/src/cache/BrowserCacheManager.ts @@ -36,6 +36,7 @@ import { PerformanceEvents, IPerformanceClient, StaticAuthorityOptions, + CacheHelpers, } from "@azure/msal-common"; import { CacheOptions } from "../config/Configuration"; import { @@ -234,17 +235,15 @@ export class BrowserCacheManager extends CacheManager { if (credObj && credObj.hasOwnProperty("credentialType")) { switch (credObj["credentialType"]) { case CredentialType.ID_TOKEN: - if (IdTokenEntity.isIdTokenEntity(credObj)) { + if (CacheHelpers.isIdTokenEntity(credObj)) { this.logger.trace( "BrowserCacheManager:createKeyMaps - idToken found, saving key to token key map" ); this.logger.tracePii( `BrowserCacheManager:createKeyMaps - idToken with key: ${key} found, saving key to token key map` ); - const idTokenEntity = CacheManager.toObject( - new IdTokenEntity(), - credObj - ); + const idTokenEntity = + credObj as IdTokenEntity; const newKey = this.updateCredentialCacheKey( key, @@ -266,11 +265,7 @@ export class BrowserCacheManager extends CacheManager { break; case CredentialType.ACCESS_TOKEN: case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME: - if ( - AccessTokenEntity.isAccessTokenEntity( - credObj - ) - ) { + if (CacheHelpers.isAccessTokenEntity(credObj)) { this.logger.trace( "BrowserCacheManager:createKeyMaps - accessToken found, saving key to token key map" ); @@ -278,10 +273,7 @@ export class BrowserCacheManager extends CacheManager { `BrowserCacheManager:createKeyMaps - accessToken with key: ${key} found, saving key to token key map` ); const accessTokenEntity = - CacheManager.toObject( - new AccessTokenEntity(), - credObj - ); + credObj as AccessTokenEntity; const newKey = this.updateCredentialCacheKey( key, @@ -303,9 +295,7 @@ export class BrowserCacheManager extends CacheManager { break; case CredentialType.REFRESH_TOKEN: if ( - RefreshTokenEntity.isRefreshTokenEntity( - credObj - ) + CacheHelpers.isRefreshTokenEntity(credObj) ) { this.logger.trace( "BrowserCacheManager:createKeyMaps - refreshToken found, saving key to token key map" @@ -314,10 +304,7 @@ export class BrowserCacheManager extends CacheManager { `BrowserCacheManager:createKeyMaps - refreshToken with key: ${key} found, saving key to token key map` ); const refreshTokenEntity = - CacheManager.toObject( - new RefreshTokenEntity(), - credObj - ); + credObj as RefreshTokenEntity; const newKey = this.updateCredentialCacheKey( key, @@ -718,7 +705,7 @@ export class BrowserCacheManager extends CacheManager { } const parsedIdToken = this.validateAndParseJson(value); - if (!parsedIdToken || !IdTokenEntity.isIdTokenEntity(parsedIdToken)) { + if (!parsedIdToken || !CacheHelpers.isIdTokenEntity(parsedIdToken)) { this.logger.trace( "BrowserCacheManager.getIdTokenCredential: called, no cache hit" ); @@ -729,7 +716,7 @@ export class BrowserCacheManager extends CacheManager { this.logger.trace( "BrowserCacheManager.getIdTokenCredential: cache hit" ); - return CacheManager.toObject(new IdTokenEntity(), parsedIdToken); + return parsedIdToken as IdTokenEntity; } /** @@ -738,7 +725,7 @@ export class BrowserCacheManager extends CacheManager { */ setIdTokenCredential(idToken: IdTokenEntity): void { this.logger.trace("BrowserCacheManager.setIdTokenCredential called"); - const idTokenKey = idToken.generateCredentialKey(); + const idTokenKey = CacheHelpers.generateCredentialKey(idToken); this.setItem(idTokenKey, JSON.stringify(idToken)); @@ -761,7 +748,7 @@ export class BrowserCacheManager extends CacheManager { const parsedAccessToken = this.validateAndParseJson(value); if ( !parsedAccessToken || - !AccessTokenEntity.isAccessTokenEntity(parsedAccessToken) + !CacheHelpers.isAccessTokenEntity(parsedAccessToken) ) { this.logger.trace( "BrowserCacheManager.getAccessTokenCredential: called, no cache hit" @@ -773,10 +760,7 @@ export class BrowserCacheManager extends CacheManager { this.logger.trace( "BrowserCacheManager.getAccessTokenCredential: cache hit" ); - return CacheManager.toObject( - new AccessTokenEntity(), - parsedAccessToken - ); + return parsedAccessToken as AccessTokenEntity; } /** @@ -787,7 +771,7 @@ export class BrowserCacheManager extends CacheManager { this.logger.trace( "BrowserCacheManager.setAccessTokenCredential called" ); - const accessTokenKey = accessToken.generateCredentialKey(); + const accessTokenKey = CacheHelpers.generateCredentialKey(accessToken); this.setItem(accessTokenKey, JSON.stringify(accessToken)); this.addTokenKey(accessTokenKey, CredentialType.ACCESS_TOKEN); @@ -811,7 +795,7 @@ export class BrowserCacheManager extends CacheManager { const parsedRefreshToken = this.validateAndParseJson(value); if ( !parsedRefreshToken || - !RefreshTokenEntity.isRefreshTokenEntity(parsedRefreshToken) + !CacheHelpers.isRefreshTokenEntity(parsedRefreshToken) ) { this.logger.trace( "BrowserCacheManager.getRefreshTokenCredential: called, no cache hit" @@ -823,10 +807,7 @@ export class BrowserCacheManager extends CacheManager { this.logger.trace( "BrowserCacheManager.getRefreshTokenCredential: cache hit" ); - return CacheManager.toObject( - new RefreshTokenEntity(), - parsedRefreshToken - ); + return parsedRefreshToken as RefreshTokenEntity; } /** @@ -837,7 +818,8 @@ export class BrowserCacheManager extends CacheManager { this.logger.trace( "BrowserCacheManager.setRefreshTokenCredential called" ); - const refreshTokenKey = refreshToken.generateCredentialKey(); + const refreshTokenKey = + CacheHelpers.generateCredentialKey(refreshToken); this.setItem(refreshTokenKey, JSON.stringify(refreshToken)); this.addTokenKey(refreshTokenKey, CredentialType.REFRESH_TOKEN); @@ -1804,7 +1786,7 @@ export class BrowserCacheManager extends CacheManager { currentCacheKey: string, credential: ValidCredentialType ): string { - const updatedCacheKey = credential.generateCredentialKey(); + const updatedCacheKey = CacheHelpers.generateCredentialKey(credential); if (currentCacheKey !== updatedCacheKey) { const cacheItem = this.getItem(currentCacheKey); @@ -1860,7 +1842,7 @@ export class BrowserCacheManager extends CacheManager { | RedirectRequest | PopupRequest ): Promise { - const idTokenEntity = IdTokenEntity.createIdTokenEntity( + const idTokenEntity = CacheHelpers.createIdTokenEntity( result.account?.homeAccountId, result.account?.environment, result.idToken, @@ -1872,7 +1854,7 @@ export class BrowserCacheManager extends CacheManager { if (request.claims) { claimsHash = await this.cryptoImpl.hashString(request.claims); } - const accessTokenEntity = AccessTokenEntity.createAccessTokenEntity( + const accessTokenEntity = CacheHelpers.createAccessTokenEntity( result.account?.homeAccountId, result.account.environment, result.accessToken, @@ -1881,7 +1863,7 @@ export class BrowserCacheManager extends CacheManager { result.scopes.join(" "), result.expiresOn?.getTime() || 0, result.extExpiresOn?.getTime() || 0, - this.cryptoImpl, + base64Decode, undefined, // refreshOn result.tokenType as AuthenticationScheme, undefined, // userAssertionHash diff --git a/lib/msal-browser/src/cache/TokenCache.ts b/lib/msal-browser/src/cache/TokenCache.ts index 2408a91a01..cad72715a9 100644 --- a/lib/msal-browser/src/cache/TokenCache.ts +++ b/lib/msal-browser/src/cache/TokenCache.ts @@ -18,6 +18,7 @@ import { Constants, CacheRecord, TokenClaims, + CacheHelpers, } from "@azure/msal-common"; import { BrowserConfiguration } from "../config/Configuration"; import { SilentRequest } from "../request/SilentRequest"; @@ -294,7 +295,7 @@ export class TokenCache implements ITokenCache { environment: string, tenantId: string ): IdTokenEntity { - const idTokenEntity = IdTokenEntity.createIdTokenEntity( + const idTokenEntity = CacheHelpers.createIdTokenEntity( homeAccountId, environment, idToken, @@ -355,7 +356,7 @@ export class TokenCache implements ITokenCache { response.expires_in + new Date().getTime() / 1000; const extendedExpiresOn = options.extendedExpiresOn; - const accessTokenEntity = AccessTokenEntity.createAccessTokenEntity( + const accessTokenEntity = CacheHelpers.createAccessTokenEntity( homeAccountId, environment, response.access_token, @@ -364,7 +365,7 @@ export class TokenCache implements ITokenCache { scopes, expiresOn, extendedExpiresOn, - this.cryptoObj + base64Decode ); if (this.isBrowserEnvironment) { @@ -399,7 +400,7 @@ export class TokenCache implements ITokenCache { return null; } - const refreshTokenEntity = RefreshTokenEntity.createRefreshTokenEntity( + const refreshTokenEntity = CacheHelpers.createRefreshTokenEntity( homeAccountId, environment, response.refresh_token, diff --git a/lib/msal-browser/src/interaction_client/NativeInteractionClient.ts b/lib/msal-browser/src/interaction_client/NativeInteractionClient.ts index 96a187fdf3..c8eba043d1 100644 --- a/lib/msal-browser/src/interaction_client/NativeInteractionClient.ts +++ b/lib/msal-browser/src/interaction_client/NativeInteractionClient.ts @@ -33,6 +33,7 @@ import { invokeAsync, createAuthError, AuthErrorCodes, + CacheHelpers, } from "@azure/msal-common"; import { BaseInteractionClient } from "./BaseInteractionClient"; import { BrowserConfiguration } from "../config/Configuration"; @@ -656,7 +657,7 @@ export class NativeInteractionClient extends BaseInteractionClient { reqTimestamp: number ): void { const cachedIdToken: IdTokenEntity | null = - IdTokenEntity.createIdTokenEntity( + CacheHelpers.createIdTokenEntity( homeAccountIdentifier, request.authority, response.id_token || "", @@ -675,7 +676,7 @@ export class NativeInteractionClient extends BaseInteractionClient { const responseScopes = this.generateScopes(response, request); const cachedAccessToken: AccessTokenEntity | null = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( homeAccountIdentifier, request.authority, responseAccessToken, @@ -684,7 +685,7 @@ export class NativeInteractionClient extends BaseInteractionClient { responseScopes.printScopes(), tokenExpirationSeconds, 0, - this.browserCrypto + base64Decode ); const nativeCacheRecord = new CacheRecord( diff --git a/lib/msal-browser/test/app/PublicClientApplication.spec.ts b/lib/msal-browser/test/app/PublicClientApplication.spec.ts index c66e8e7158..bacaa3bdbc 100644 --- a/lib/msal-browser/test/app/PublicClientApplication.spec.ts +++ b/lib/msal-browser/test/app/PublicClientApplication.spec.ts @@ -52,6 +52,7 @@ import { ClientAuthErrorCodes, createInteractionRequiredAuthError, InteractionRequiredAuthErrorCodes, + CacheHelpers, } from "@azure/msal-common"; import { ApiId, @@ -5043,7 +5044,7 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { testAccount1.clientInfo = TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; - const idTokenData1 = { + const idToken1: IdTokenEntity = { realm: testAccountInfo1.tenantId, environment: testAccountInfo1.environment, credentialType: "IdToken", @@ -5073,10 +5074,6 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { // @ts-ignore pca.getBrowserStorage().setAccount(testAccount1); - const idToken1 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData1 - ); // @ts-ignore pca.getBrowserStorage().setIdTokenCredential(idToken1); }); @@ -5137,7 +5134,7 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { testAccount1.clientInfo = TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; - const idTokenData1 = { + const idToken1: IdTokenEntity = { realm: testAccountInfo1.tenantId, environment: testAccountInfo1.environment, credentialType: "IdToken", @@ -5171,7 +5168,7 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { testAccount2.clientInfo = TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; - const idTokenData2 = { + const idToken2: IdTokenEntity = { realm: testAccountInfo2.tenantId, environment: testAccountInfo2.environment, credentialType: "IdToken", @@ -5207,14 +5204,13 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; testAccount3.idTokenClaims = testAccountInfo3.idTokenClaims; - const idTokenData3 = { + const idToken3: IdTokenEntity = { realm: testAccountInfo3.tenantId, environment: testAccountInfo3.environment, credentialType: "IdToken", secret: TEST_TOKENS.ID_TOKEN_V2_WITH_LOGIN_HINT, clientId: TEST_CONFIG.MSAL_CLIENT_ID, homeAccountId: testAccountInfo3.homeAccountId, - login_hint: "testLoginHint", }; // Account 4 @@ -5244,14 +5240,13 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; testAccount4.idTokenClaims = testAccountInfo4.idTokenClaims; - const idTokenData4 = { + const idToken4: IdTokenEntity = { realm: testAccountInfo4.tenantId, environment: testAccountInfo4.environment, credentialType: "IdToken", secret: TEST_TOKENS.ID_TOKEN_V2_WITH_UPN, clientId: TEST_CONFIG.MSAL_CLIENT_ID, homeAccountId: testAccountInfo4.homeAccountId, - upn: "testUpn", }; beforeEach(async () => { @@ -5281,31 +5276,14 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { // @ts-ignore pca.getBrowserStorage().setAccount(testAccount4); - const idToken1 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData1 - ); // @ts-ignore pca.getBrowserStorage().setIdTokenCredential(idToken1); - const idToken2 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData2 - ); // @ts-ignore pca.getBrowserStorage().setIdTokenCredential(idToken2); - - const idToken3 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData3 - ); // @ts-ignore pca.getBrowserStorage().setIdTokenCredential(idToken3); - const idToken4 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData4 - ); // @ts-ignore pca.getBrowserStorage().setIdTokenCredential(idToken4); }); @@ -5510,7 +5488,7 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { testAccount1.clientInfo = TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; - const idTokenData1 = { + const idToken1: IdTokenEntity = { realm: testAccountInfo1.tenantId, environment: testAccountInfo1.environment, credentialType: "IdToken", @@ -5519,11 +5497,6 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { homeAccountId: testAccountInfo1.homeAccountId, }; - const idToken1 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData1 - ); - // Account 2 const testAccountInfo2: AccountInfo = { authorityType: "MSSTS", @@ -5551,7 +5524,7 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; testAccount2.idTokenClaims = ID_TOKEN_CLAIMS; - const idTokenData2 = { + const idToken2: IdTokenEntity = { realm: testAccountInfo2.tenantId, environment: testAccountInfo2.environment, credentialType: "IdToken", @@ -5559,10 +5532,6 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { clientId: TEST_CONFIG.MSAL_CLIENT_ID, homeAccountId: testAccountInfo2.homeAccountId, }; - const idToken2 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData2 - ); beforeEach(async () => { pca = (pca as any).controller; @@ -5721,7 +5690,8 @@ describe("PublicClientApplication.ts Class Unit Tests", () => { const cacheKey2 = AccountEntity.generateAccountCacheKey(testAccountInfo2); - const idTokenKey2 = idToken2.generateCredentialKey(); + const idTokenKey2 = + CacheHelpers.generateCredentialKey(idToken2); window.sessionStorage.removeItem(cacheKey2); window.sessionStorage.removeItem(idTokenKey2); expect(pca.getActiveAccount()).toBe(null); diff --git a/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts b/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts index dc4c3b6b29..c57aa2d428 100644 --- a/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts +++ b/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts @@ -28,17 +28,12 @@ import { Authority, StubbedNetworkModule, AuthToken, - IdTokenEntity, - AccessTokenEntity, - RefreshTokenEntity, AppMetadataEntity, ServerTelemetryEntity, ThrottlingEntity, CredentialType, ProtocolMode, - AccountInfo, - AuthError, - ClientAuthErrorMessage, + CacheHelpers, } from "@azure/msal-common"; import { BrowserCacheLocation, @@ -203,14 +198,14 @@ describe("BrowserCacheManager tests", () => { it("Adds existing tokens to token key map on initialization", () => { // Pre-populate localstorage with tokens - const testIdToken = IdTokenEntity.createIdTokenEntity( + const testIdToken = CacheHelpers.createIdTokenEntity( "homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, TEST_CONFIG.MSAL_CLIENT_ID, "tenantId" ); - const testAccessToken = AccessTokenEntity.createAccessTokenEntity( + const testAccessToken = CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -219,25 +214,24 @@ describe("BrowserCacheManager tests", () => { "scope", 1000, 1000, - browserCrypto - ); - const testRefreshToken = - RefreshTokenEntity.createRefreshTokenEntity( - "homeAccountId", - "environment", - TEST_TOKENS.REFRESH_TOKEN, - TEST_CONFIG.MSAL_CLIENT_ID - ); + browserCrypto.base64Decode + ); + const testRefreshToken = CacheHelpers.createRefreshTokenEntity( + "homeAccountId", + "environment", + TEST_TOKENS.REFRESH_TOKEN, + TEST_CONFIG.MSAL_CLIENT_ID + ); window.localStorage.setItem( - testIdToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testIdToken), JSON.stringify(testIdToken) ); window.localStorage.setItem( - testAccessToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAccessToken), JSON.stringify(testAccessToken) ); window.localStorage.setItem( - testRefreshToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testRefreshToken), JSON.stringify(testRefreshToken) ); @@ -280,14 +274,14 @@ describe("BrowserCacheManager tests", () => { it("Does not add tokens for other clientIds to token key map", () => { // Pre-populate localstorage with tokens - const testIdToken = IdTokenEntity.createIdTokenEntity( + const testIdToken = CacheHelpers.createIdTokenEntity( "homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, "other-client-id", "tenantId" ); - const testAccessToken = AccessTokenEntity.createAccessTokenEntity( + const testAccessToken = CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -296,25 +290,24 @@ describe("BrowserCacheManager tests", () => { "scope", 1000, 1000, - browserCrypto - ); - const testRefreshToken = - RefreshTokenEntity.createRefreshTokenEntity( - "homeAccountId", - "environment", - TEST_TOKENS.REFRESH_TOKEN, - "other-client-id" - ); + browserCrypto.base64Decode + ); + const testRefreshToken = CacheHelpers.createRefreshTokenEntity( + "homeAccountId", + "environment", + TEST_TOKENS.REFRESH_TOKEN, + "other-client-id" + ); window.localStorage.setItem( - testIdToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testIdToken), JSON.stringify(testIdToken) ); window.localStorage.setItem( - testAccessToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAccessToken), JSON.stringify(testAccessToken) ); window.localStorage.setItem( - testRefreshToken.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testRefreshToken), JSON.stringify(testRefreshToken) ); @@ -650,7 +643,7 @@ describe("BrowserCacheManager tests", () => { }); it("getIdTokenCredential returns IdTokenEntity", () => { - const testIdToken = IdTokenEntity.createIdTokenEntity( + const testIdToken = CacheHelpers.createIdTokenEntity( "homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, @@ -663,24 +656,14 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testIdToken) ) ).toEqual(testIdToken); - expect( - browserSessionStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() - ) - ).toBeInstanceOf(IdTokenEntity); expect( browserLocalStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testIdToken) ) ).toEqual(testIdToken); - expect( - browserLocalStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() - ) - ).toBeInstanceOf(IdTokenEntity); }); }); @@ -733,7 +716,7 @@ describe("BrowserCacheManager tests", () => { it("getAccessTokenCredential returns AccessTokenEntity", () => { const testAccessToken = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -742,7 +725,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" @@ -757,29 +740,19 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAccessToken) ) ).toEqual(testAccessToken); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAccessToken) ) ).toEqual(testAccessToken); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); it("getAccessTokenCredential returns Bearer access token when authentication scheme is set to Bearer and both a Bearer and pop token are in the cache", () => { const testAccessTokenWithoutAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -788,13 +761,13 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); const testAccessTokenWithAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.POP_TOKEN, @@ -803,7 +776,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.POP, "oboAssertion" @@ -819,7 +792,7 @@ describe("BrowserCacheManager tests", () => { it("getAccessTokenCredential returns Bearer access token when authentication scheme is set to Bearer and both a Bearer and pop token are in the cache", () => { const testAccessTokenWithoutAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -828,13 +801,13 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); const testAccessTokenWithAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.POP_TOKEN, @@ -843,7 +816,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.POP, "oboAssertion" @@ -866,39 +839,37 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) ) ).toEqual(testAccessTokenWithoutAuthScheme); expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) ) ).toEqual(testAccessTokenWithoutAuthScheme); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); it("getAccessTokenCredential returns PoP access token when authentication scheme is set to pop and both a Bearer and pop token are in the cache", () => { const testAccessTokenWithoutAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -907,13 +878,13 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); const testAccessTokenWithAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.POP_TOKEN, @@ -922,7 +893,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.POP, "oboAssertion" @@ -945,38 +916,36 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) ) ).toEqual(testAccessTokenWithAuthScheme); expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) ) ).toEqual(testAccessTokenWithAuthScheme); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); it("clearTokensWithClaimsInCache clears all access tokens with claims in tokenKeys", () => { - const testAT1 = AccessTokenEntity.createAccessTokenEntity( + const testAT1 = CacheHelpers.createAccessTokenEntity( "homeAccountId1", "environment", "secret1", @@ -985,12 +954,12 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); - const testAT2 = AccessTokenEntity.createAccessTokenEntity( + const testAT2 = CacheHelpers.createAccessTokenEntity( "homeAccountId2", "environment", "secret2", @@ -999,7 +968,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion", @@ -1007,7 +976,7 @@ describe("BrowserCacheManager tests", () => { "claims", "claims-hash" ); - const testAT3 = AccessTokenEntity.createAccessTokenEntity( + const testAT3 = CacheHelpers.createAccessTokenEntity( "homeAccountId3", "environment", "secret3", @@ -1016,14 +985,14 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion", undefined, "claims" ); - const testAT4 = AccessTokenEntity.createAccessTokenEntity( + const testAT4 = CacheHelpers.createAccessTokenEntity( "homeAccountId4", "environment", "secret4", @@ -1032,7 +1001,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion", @@ -1065,10 +1034,10 @@ describe("BrowserCacheManager tests", () => { expect(browserLocalStorage.getTokenKeys()).toStrictEqual({ idToken: [], accessToken: [ - testAT1.generateCredentialKey(), - testAT2.generateCredentialKey(), - testAT3.generateCredentialKey(), - testAT4.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAT1), + CacheHelpers.generateCredentialKey(testAT2), + CacheHelpers.generateCredentialKey(testAT3), + CacheHelpers.generateCredentialKey(testAT4), ], refreshToken: [], }); @@ -1076,10 +1045,10 @@ describe("BrowserCacheManager tests", () => { expect(browserSessionStorage.getTokenKeys()).toStrictEqual({ idToken: [], accessToken: [ - testAT1.generateCredentialKey(), - testAT2.generateCredentialKey(), - testAT3.generateCredentialKey(), - testAT4.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAT1), + CacheHelpers.generateCredentialKey(testAT2), + CacheHelpers.generateCredentialKey(testAT3), + CacheHelpers.generateCredentialKey(testAT4), ], refreshToken: [], }); @@ -1093,87 +1062,47 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT1) ) ).toEqual(testAT1); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT1) ) ).toEqual(testAT1); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserSessionStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toEqual(testAT2); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toEqual(testAT2); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserSessionStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT3) ) ).toEqual(testAT3); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT3) ) ).toEqual(testAT3); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserSessionStorage.getAccessTokenCredential( - testAT4.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT4) ) ).toEqual(testAT4); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT4.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT4.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT4) ) ).toEqual(testAT4); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT4.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); browserSessionStorage.clearTokensAndKeysWithClaims( getDefaultPerformanceClient() @@ -1184,73 +1113,53 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT1) ) ).toEqual(testAT1); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT1) ) ).toEqual(testAT1); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT1.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserSessionStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toBeNull(); expect( browserLocalStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toBeNull(); expect( browserSessionStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT3) ) ).toEqual(testAT3); - expect( - browserSessionStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT3) ) ).toEqual(testAT3); - expect( - browserLocalStorage.getAccessTokenCredential( - testAT3.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserSessionStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toBeNull(); expect( browserLocalStorage.getAccessTokenCredential( - testAT2.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAT2) ) ).toBeNull(); expect(browserLocalStorage.getTokenKeys()).toStrictEqual({ idToken: [], accessToken: [ - testAT1.generateCredentialKey(), - testAT3.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAT1), + CacheHelpers.generateCredentialKey(testAT3), ], refreshToken: [], }); @@ -1258,8 +1167,8 @@ describe("BrowserCacheManager tests", () => { expect(browserSessionStorage.getTokenKeys()).toStrictEqual({ idToken: [], accessToken: [ - testAT1.generateCredentialKey(), - testAT3.generateCredentialKey(), + CacheHelpers.generateCredentialKey(testAT1), + CacheHelpers.generateCredentialKey(testAT3), ], refreshToken: [], }); @@ -1322,7 +1231,7 @@ describe("BrowserCacheManager tests", () => { it("getRefreshTokenCredential returns RefreshTokenEntity", () => { const testRefreshToken = - RefreshTokenEntity.createRefreshTokenEntity( + CacheHelpers.createRefreshTokenEntity( "homeAccountId", "environment", TEST_TOKENS.REFRESH_TOKEN, @@ -1340,24 +1249,14 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testRefreshToken) ) ).toEqual(testRefreshToken); - expect( - browserSessionStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() - ) - ).toBeInstanceOf(RefreshTokenEntity); expect( browserLocalStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testRefreshToken) ) ).toEqual(testRefreshToken); - expect( - browserLocalStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() - ) - ).toBeInstanceOf(RefreshTokenEntity); }); }); @@ -1931,7 +1830,7 @@ describe("BrowserCacheManager tests", () => { }); it("getIdTokenCredential returns IdTokenEntity", () => { - const testIdToken = IdTokenEntity.createIdTokenEntity( + const testIdToken = CacheHelpers.createIdTokenEntity( "homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, @@ -1944,24 +1843,14 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testIdToken) ) ).toEqual(testIdToken); - expect( - browserSessionStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() - ) - ).toBeInstanceOf(IdTokenEntity); expect( browserLocalStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testIdToken) ) ).toEqual(testIdToken); - expect( - browserLocalStorage.getIdTokenCredential( - testIdToken.generateCredentialKey() - ) - ).toBeInstanceOf(IdTokenEntity); }); }); @@ -2014,7 +1903,7 @@ describe("BrowserCacheManager tests", () => { it("getAccessTokenCredential returns AccessTokenEntity", () => { const testAccessToken = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -2023,7 +1912,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" @@ -2038,29 +1927,19 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAccessToken) ) ).toEqual(testAccessToken); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testAccessToken) ) ).toEqual(testAccessToken); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessToken.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); it("getAccessTokenCredential returns Bearer access token when authentication scheme is set to Bearer and both a Bearer and pop token are in the cache", () => { const testAccessTokenWithoutAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -2069,13 +1948,13 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); const testAccessTokenWithAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.POP_TOKEN, @@ -2084,7 +1963,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.POP, "oboAssertion" @@ -2107,39 +1986,37 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) ) ).toEqual(testAccessTokenWithoutAuthScheme); expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) ) ).toEqual(testAccessTokenWithoutAuthScheme); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithoutAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithoutAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); it("getAccessTokenCredential returns PoP access token when authentication scheme is set to pop and both a Bearer and pop token are in the cache", () => { const testAccessTokenWithoutAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.ACCESS_TOKEN, @@ -2148,13 +2025,13 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.BEARER, "oboAssertion" ); const testAccessTokenWithAuthScheme = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "homeAccountId", "environment", TEST_TOKENS.POP_TOKEN, @@ -2163,7 +2040,7 @@ describe("BrowserCacheManager tests", () => { "openid", 1000, 1000, - browserCrypto, + browserCrypto.base64Decode, 500, AuthenticationScheme.POP, "oboAssertion" @@ -2186,34 +2063,32 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) ) ).toEqual(testAccessTokenWithAuthScheme); expect( browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME); - expect( - browserSessionStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) ) ).toEqual(testAccessTokenWithAuthScheme); expect( browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey( + testAccessTokenWithAuthScheme + ) )?.credentialType ).toBe(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME); - expect( - browserLocalStorage.getAccessTokenCredential( - testAccessTokenWithAuthScheme.generateCredentialKey() - ) - ).toBeInstanceOf(AccessTokenEntity); }); }); @@ -2266,7 +2141,7 @@ describe("BrowserCacheManager tests", () => { it("getRefreshTokenCredential returns RefreshTokenEntity", () => { const testRefreshToken = - RefreshTokenEntity.createRefreshTokenEntity( + CacheHelpers.createRefreshTokenEntity( "homeAccountId", "environment", TEST_TOKENS.REFRESH_TOKEN, @@ -2284,24 +2159,14 @@ describe("BrowserCacheManager tests", () => { expect( browserSessionStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testRefreshToken) ) ).toEqual(testRefreshToken); - expect( - browserSessionStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() - ) - ).toBeInstanceOf(RefreshTokenEntity); expect( browserLocalStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() + CacheHelpers.generateCredentialKey(testRefreshToken) ) ).toEqual(testRefreshToken); - expect( - browserLocalStorage.getRefreshTokenCredential( - testRefreshToken.generateCredentialKey() - ) - ).toBeInstanceOf(RefreshTokenEntity); }); }); diff --git a/lib/msal-browser/test/cache/TestStorageManager.ts b/lib/msal-browser/test/cache/TestStorageManager.ts index dcbc28c001..a0d5f27cfb 100644 --- a/lib/msal-browser/test/cache/TestStorageManager.ts +++ b/lib/msal-browser/test/cache/TestStorageManager.ts @@ -12,11 +12,10 @@ import { AppMetadataEntity, ServerTelemetryEntity, ThrottlingEntity, - CredentialEntity, - CredentialType, AuthorityMetadataEntity, ValidCredentialType, TokenKeys, + CacheHelpers, } from "@azure/msal-common"; const ACCOUNT_KEYS = "ACCOUNT_KEYS"; @@ -75,7 +74,7 @@ export class TestStorageManager extends CacheManager { } setIdTokenCredential(idToken: IdTokenEntity): void { - const idTokenKey = idToken.generateCredentialKey(); + const idTokenKey = CacheHelpers.generateCredentialKey(idToken); this.store[idTokenKey] = idToken; const tokenKeys = this.getTokenKeys(); @@ -89,7 +88,7 @@ export class TestStorageManager extends CacheManager { } setAccessTokenCredential(accessToken: AccessTokenEntity): void { - const accessTokenKey = accessToken.generateCredentialKey(); + const accessTokenKey = CacheHelpers.generateCredentialKey(accessToken); this.store[accessTokenKey] = accessToken; const tokenKeys = this.getTokenKeys(); @@ -102,7 +101,8 @@ export class TestStorageManager extends CacheManager { return (this.store[key] as RefreshTokenEntity) || null; } setRefreshTokenCredential(refreshToken: RefreshTokenEntity): void { - const refreshTokenKey = refreshToken.generateCredentialKey(); + const refreshTokenKey = + CacheHelpers.generateCredentialKey(refreshToken); this.store[refreshTokenKey] = refreshToken; const tokenKeys = this.getTokenKeys(); @@ -173,7 +173,7 @@ export class TestStorageManager extends CacheManager { currentCacheKey: string, credential: ValidCredentialType ): string { - const updatedCacheKey = credential.generateCredentialKey(); + const updatedCacheKey = CacheHelpers.generateCredentialKey(credential); if (currentCacheKey !== updatedCacheKey) { const cacheItem = this.store[currentCacheKey]; diff --git a/lib/msal-browser/test/cache/TokenCache.spec.ts b/lib/msal-browser/test/cache/TokenCache.spec.ts index b5c01f9a01..951886331a 100644 --- a/lib/msal-browser/test/cache/TokenCache.spec.ts +++ b/lib/msal-browser/test/cache/TokenCache.spec.ts @@ -16,6 +16,7 @@ import { AuthorityType, RefreshTokenEntity, TokenClaims, + CacheHelpers, } from "@azure/msal-common"; import { TokenCache, LoadTokenOptions } from "../../src/cache/TokenCache"; import { CryptoOps } from "../../src/crypto/CryptoOps"; @@ -124,20 +125,20 @@ describe("TokenCache tests", () => { testIdTokenClaims ); - idTokenEntity = IdTokenEntity.createIdTokenEntity( + idTokenEntity = CacheHelpers.createIdTokenEntity( testHomeAccountId, testEnvironment, TEST_TOKENS.IDTOKEN_V2, configuration.auth.clientId, TEST_CONFIG.TENANT ); - idTokenKey = idTokenEntity.generateCredentialKey(); + idTokenKey = CacheHelpers.generateCredentialKey(idTokenEntity); scopeString = new ScopeSet( TEST_CONFIG.DEFAULT_SCOPES ).printScopes(); (testAccessToken = TEST_TOKENS.ACCESS_TOKEN), - (accessTokenEntity = AccessTokenEntity.createAccessTokenEntity( + (accessTokenEntity = CacheHelpers.createAccessTokenEntity( testHomeAccountId, testEnvironment, testAccessToken, @@ -146,18 +147,20 @@ describe("TokenCache tests", () => { scopeString, TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP, TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP, - cryptoObj + cryptoObj.base64Decode )); - accessTokenKey = accessTokenEntity.generateCredentialKey(); + accessTokenKey = + CacheHelpers.generateCredentialKey(accessTokenEntity); testRefreshToken = TEST_TOKENS.REFRESH_TOKEN; - refreshTokenEntity = RefreshTokenEntity.createRefreshTokenEntity( + refreshTokenEntity = CacheHelpers.createRefreshTokenEntity( testHomeAccountId, testEnvironment, testRefreshToken, configuration.auth.clientId ); - refreshTokenKey = refreshTokenEntity.generateCredentialKey(); + refreshTokenKey = + CacheHelpers.generateCredentialKey(refreshTokenEntity); }); afterEach(() => { @@ -187,14 +190,15 @@ describe("TokenCache tests", () => { options ); - const testIdTokenEntity = IdTokenEntity.createIdTokenEntity( + const testIdTokenEntity = CacheHelpers.createIdTokenEntity( requestHomeAccountId, testEnvironment, TEST_TOKENS.IDTOKEN_V2, configuration.auth.clientId, TEST_CONFIG.TENANT ); - const testIdTokenKey = testIdTokenEntity.generateCredentialKey(); + const testIdTokenKey = + CacheHelpers.generateCredentialKey(testIdTokenEntity); expect(result.idToken).toEqual(TEST_TOKENS.IDTOKEN_V2); expect(browserStorage.getIdTokenCredential(testIdTokenKey)).toEqual( diff --git a/lib/msal-browser/test/interaction_client/BaseInteractionClient.spec.ts b/lib/msal-browser/test/interaction_client/BaseInteractionClient.spec.ts index 850d94f7a2..6466e1e03e 100644 --- a/lib/msal-browser/test/interaction_client/BaseInteractionClient.spec.ts +++ b/lib/msal-browser/test/interaction_client/BaseInteractionClient.spec.ts @@ -94,7 +94,7 @@ describe("BaseInteractionClient", () => { username: testIdTokenClaims.preferred_username || "", }; - const idTokenData1 = { + const idToken1: IdTokenEntity = { realm: testAccountInfo1.tenantId, environment: testAccountInfo1.environment, credentialType: "IdToken", @@ -103,11 +103,6 @@ describe("BaseInteractionClient", () => { homeAccountId: testAccountInfo1.homeAccountId, }; - const idToken1 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData1 - ); - const testAccount1: AccountEntity = new AccountEntity(); testAccount1.homeAccountId = testAccountInfo1.homeAccountId; testAccount1.localAccountId = testAccountInfo1.localAccountId; @@ -127,7 +122,7 @@ describe("BaseInteractionClient", () => { username: testIdTokenClaims.preferred_username || "", }; - const idTokenData2 = { + const idToken2: IdTokenEntity = { realm: testAccountInfo2.tenantId, environment: testAccountInfo2.environment, credentialType: "IdToken", @@ -136,11 +131,6 @@ describe("BaseInteractionClient", () => { homeAccountId: testAccountInfo2.homeAccountId, }; - const idToken2 = CacheManager.toObject( - new IdTokenEntity(), - idTokenData2 - ); - const testAccount2: AccountEntity = new AccountEntity(); testAccount2.homeAccountId = testAccountInfo2.homeAccountId; testAccount2.localAccountId = testAccountInfo2.localAccountId; diff --git a/lib/msal-browser/test/interaction_client/NativeInteractionClient.spec.ts b/lib/msal-browser/test/interaction_client/NativeInteractionClient.spec.ts index 4b56f07e66..6a2f40e524 100644 --- a/lib/msal-browser/test/interaction_client/NativeInteractionClient.spec.ts +++ b/lib/msal-browser/test/interaction_client/NativeInteractionClient.spec.ts @@ -67,27 +67,27 @@ const testAccountInfo: AccountInfo = { idTokenClaims: ID_TOKEN_CLAIMS, }; -const testIdToken: IdTokenEntity = new IdTokenEntity(); -testIdToken.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; -testIdToken.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testIdToken.environment = testAccountEntity.environment; -testIdToken.realm = ID_TOKEN_CLAIMS.tid; -testIdToken.secret = TEST_TOKENS.IDTOKEN_V2; -testIdToken.credentialType = CredentialType.ID_TOKEN; - -const testAccessTokenEntity: AccessTokenEntity = new AccessTokenEntity(); -testAccessTokenEntity.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; -testAccessTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testAccessTokenEntity.environment = testAccountEntity.environment; -testAccessTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testAccessTokenEntity.secret = TEST_TOKENS.ACCESS_TOKEN; -testAccessTokenEntity.target = TEST_CONFIG.DEFAULT_SCOPES.join(" "); -testAccessTokenEntity.credentialType = CredentialType.ACCESS_TOKEN; -testAccessTokenEntity.expiresOn = `${ - TimeUtils.nowSeconds() + TEST_CONFIG.TOKEN_EXPIRY -}`; -testAccessTokenEntity.cachedAt = `${TimeUtils.nowSeconds()}`; -testAccessTokenEntity.tokenType = AuthenticationScheme.BEARER; +const testIdToken: IdTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.IDTOKEN_V2, + credentialType: CredentialType.ID_TOKEN, +}; + +const testAccessTokenEntity: AccessTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.ACCESS_TOKEN, + target: TEST_CONFIG.DEFAULT_SCOPES.join(" "), + credentialType: CredentialType.ACCESS_TOKEN, + tokenType: AuthenticationScheme.BEARER, + expiresOn: `${TimeUtils.nowSeconds() + TEST_CONFIG.TOKEN_EXPIRY}`, + cachedAt: `${TimeUtils.nowSeconds()}`, +}; const testCacheRecord: CacheRecord = { account: testAccountEntity, diff --git a/lib/msal-browser/test/interaction_client/RedirectClient.spec.ts b/lib/msal-browser/test/interaction_client/RedirectClient.spec.ts index c2f74e7018..6391ca1c04 100644 --- a/lib/msal-browser/test/interaction_client/RedirectClient.spec.ts +++ b/lib/msal-browser/test/interaction_client/RedirectClient.spec.ts @@ -131,6 +131,11 @@ describe("RedirectClient", () => { RANDOM_TEST_GUID ); + jest.spyOn( + NavigationClient.prototype, + "navigateExternal" + ).mockResolvedValue(true); + // @ts-ignore browserStorage = pca.browserStorage; @@ -3673,13 +3678,14 @@ describe("RedirectClient", () => { testAccount.clientInfo = TEST_DATA_CLIENT_INFO.TEST_CLIENT_INFO_B64ENCODED; - const testIdToken: IdTokenEntity = new IdTokenEntity(); - testIdToken.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; - testIdToken.clientId = TEST_CONFIG.MSAL_CLIENT_ID; - testIdToken.environment = testAccount.environment; - testIdToken.realm = ID_TOKEN_CLAIMS.tid; - testIdToken.secret = TEST_TOKENS.IDTOKEN_V2; - testIdToken.credentialType = CredentialType.ID_TOKEN; + const testIdToken: IdTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccount.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.IDTOKEN_V2, + credentialType: CredentialType.ID_TOKEN, + }; const validatedLogoutRequest: CommonEndSessionRequest = { correlationId: RANDOM_TEST_GUID, diff --git a/lib/msal-browser/test/interaction_client/SilentCacheClient.spec.ts b/lib/msal-browser/test/interaction_client/SilentCacheClient.spec.ts index 17a8c62343..708185fb7a 100644 --- a/lib/msal-browser/test/interaction_client/SilentCacheClient.spec.ts +++ b/lib/msal-browser/test/interaction_client/SilentCacheClient.spec.ts @@ -34,33 +34,36 @@ testAccountEntity.username = ID_TOKEN_CLAIMS.preferred_username; testAccountEntity.name = ID_TOKEN_CLAIMS.name; testAccountEntity.authorityType = "MSSTS"; -const testIdToken: IdTokenEntity = new IdTokenEntity(); -testIdToken.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; -testIdToken.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testIdToken.environment = testAccountEntity.environment; -testIdToken.realm = ID_TOKEN_CLAIMS.tid; -testIdToken.secret = TEST_TOKENS.IDTOKEN_V2; -testIdToken.credentialType = CredentialType.ID_TOKEN; +const testIdToken: IdTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.IDTOKEN_V2, + credentialType: CredentialType.ID_TOKEN, +}; -const testAccessTokenEntity: AccessTokenEntity = new AccessTokenEntity(); -testAccessTokenEntity.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; -testAccessTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testAccessTokenEntity.environment = testAccountEntity.environment; -testAccessTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testAccessTokenEntity.secret = TEST_TOKENS.ACCESS_TOKEN; -testAccessTokenEntity.target = TEST_CONFIG.DEFAULT_SCOPES.join(" "); -testAccessTokenEntity.credentialType = CredentialType.ACCESS_TOKEN; -testAccessTokenEntity.expiresOn = `${TimeUtils.nowSeconds() + 3600}`; -testAccessTokenEntity.cachedAt = `${TimeUtils.nowSeconds()}`; -testAccessTokenEntity.tokenType = AuthenticationScheme.BEARER; +const testAccessTokenEntity: AccessTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.ACCESS_TOKEN, + target: TEST_CONFIG.DEFAULT_SCOPES.join(" "), + credentialType: CredentialType.ACCESS_TOKEN, + expiresOn: `${TimeUtils.nowSeconds() + 3600}`, + cachedAt: `${TimeUtils.nowSeconds()}`, + tokenType: AuthenticationScheme.BEARER, +}; -const testRefreshTokenEntity: RefreshTokenEntity = new RefreshTokenEntity(); -testRefreshTokenEntity.homeAccountId = `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`; -testRefreshTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testRefreshTokenEntity.environment = testAccountEntity.environment; -testRefreshTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testRefreshTokenEntity.secret = TEST_TOKENS.REFRESH_TOKEN; -testRefreshTokenEntity.credentialType = CredentialType.REFRESH_TOKEN; +const testRefreshTokenEntity: RefreshTokenEntity = { + homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: TEST_TOKENS.REFRESH_TOKEN, + credentialType: CredentialType.REFRESH_TOKEN, +}; const testAccount: AccountInfo = { homeAccountId: `${ID_TOKEN_CLAIMS.oid}.${ID_TOKEN_CLAIMS.tid}`, diff --git a/lib/msal-browser/test/interaction_client/SilentRefreshClient.spec.ts b/lib/msal-browser/test/interaction_client/SilentRefreshClient.spec.ts index 2a0d12decf..8acf8966fb 100644 --- a/lib/msal-browser/test/interaction_client/SilentRefreshClient.spec.ts +++ b/lib/msal-browser/test/interaction_client/SilentRefreshClient.spec.ts @@ -24,6 +24,7 @@ import { NetworkManager, RefreshTokenEntity, AccountEntity, + CredentialType, } from "@azure/msal-common"; import * as BrowserCrypto from "../../src/crypto/BrowserCrypto"; import { @@ -155,8 +156,14 @@ describe("SilentRefreshClient", () => { describe("storeInCache tests", () => { beforeEach(() => { - const rtEntity = new RefreshTokenEntity(); - rtEntity.secret = TEST_TOKEN_RESPONSE.body.refresh_token!; + const rtEntity = { + secret: TEST_TOKENS.REFRESH_TOKEN, + credentialType: CredentialType.REFRESH_TOKEN, + homeAccountId: TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, + environment: "login.windows.net", + realm: testIdTokenClaims.tid || "", + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + }; const accountEntity = new AccountEntity(); jest.spyOn( BrowserCacheManager.prototype, diff --git a/lib/msal-common/src/cache/CacheManager.ts b/lib/msal-common/src/cache/CacheManager.ts index c439048568..c6c6b76af1 100644 --- a/lib/msal-common/src/cache/CacheManager.ts +++ b/lib/msal-common/src/cache/CacheManager.ts @@ -21,6 +21,7 @@ import { Separators, } from "../utils/Constants"; import { CredentialEntity } from "./entities/CredentialEntity"; +import { generateCredentialKey } from "./utils/CacheHelpers"; import { ScopeSet } from "../request/ScopeSet"; import { AccountEntity } from "./entities/AccountEntity"; import { AccessTokenEntity } from "./entities/AccessTokenEntity"; @@ -957,7 +958,7 @@ export abstract class CacheManager implements ICacheManager { "CacheManager:getIdToken - Multiple id tokens found, clearing them" ); idTokens.forEach((idToken) => { - this.removeIdToken(idToken.generateCredentialKey()); + this.removeIdToken(generateCredentialKey(idToken)); }); return null; } @@ -1113,9 +1114,7 @@ export abstract class CacheManager implements ICacheManager { "CacheManager:getAccessToken - Multiple access tokens found, clearing them" ); accessTokens.forEach((accessToken) => { - void this.removeAccessToken( - accessToken.generateCredentialKey() - ); + void this.removeAccessToken(generateCredentialKey(accessToken)); }); return null; } diff --git a/lib/msal-common/src/cache/entities/AccessTokenEntity.ts b/lib/msal-common/src/cache/entities/AccessTokenEntity.ts index 210d2e359b..96019d2fa0 100644 --- a/lib/msal-common/src/cache/entities/AccessTokenEntity.ts +++ b/lib/msal-common/src/cache/entities/AccessTokenEntity.ts @@ -4,164 +4,28 @@ */ import { CredentialEntity } from "./CredentialEntity"; -import { CredentialType, AuthenticationScheme } from "../../utils/Constants"; -import { TimeUtils } from "../../utils/TimeUtils"; -import { ICrypto } from "../../crypto/ICrypto"; -import { TokenClaims } from "../../account/TokenClaims"; -import { - createClientAuthError, - ClientAuthErrorCodes, -} from "../../error/ClientAuthError"; -import { extractTokenClaims } from "../../account/AuthToken"; +import { AuthenticationScheme } from "../../utils/Constants"; /** - * ACCESS_TOKEN Credential Type - * - * Key:Value Schema: - * - * Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read - * - * Value Schema: - * { - * homeAccountId: home account identifier for the auth scheme, - * environment: entity that issued the token, represented as a full host - * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other - * clientId: client ID of the application - * secret: Actual credential as a string - * familyId: Family ID identifier, usually only used for refresh tokens - * realm: Full tenant or organizational identifier that the account belongs to - * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. - * cachedAt: Absolute device time when entry was created in the cache. - * expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string. - * extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds. - * keyId: used for POP and SSH tokenTypes - * tokenType: Type of the token issued. Usually "Bearer" - * } + * Access token cache type */ -export class AccessTokenEntity extends CredentialEntity { +export type AccessTokenEntity = CredentialEntity & { + /** Full tenant or organizational identifier that the account belongs to */ realm: string; + /** Permissions that are included in the token, or for refresh tokens, the resource identifier. */ target: string; + /** Absolute device time when entry was created in the cache. */ cachedAt: string; + /** Token expiry time, calculated based on current UTC time in seconds. Represented as a string. */ expiresOn: string; + /** Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds. */ extendedExpiresOn?: string; + /** Used for proactive refresh */ refreshOn?: string; - keyId?: string; // for POP and SSH tokenTypes + /** Matches the authentication scheme for which the token was issued (i.e. Bearer or pop) */ tokenType?: AuthenticationScheme; + /** Stringified claims object */ requestedClaims?: string; + /** Matches the SHA 256 hash of the claims object included in the token request */ requestedClaimsHash?: string; - - /** - * Create AccessTokenEntity - * @param homeAccountId - * @param environment - * @param accessToken - * @param clientId - * @param tenantId - * @param scopes - * @param expiresOn - * @param extExpiresOn - */ - static createAccessTokenEntity( - homeAccountId: string, - environment: string, - accessToken: string, - clientId: string, - tenantId: string, - scopes: string, - expiresOn: number, - extExpiresOn: number, - cryptoUtils: ICrypto, - refreshOn?: number, - tokenType?: AuthenticationScheme, - userAssertionHash?: string, - keyId?: string, - requestedClaims?: string, - requestedClaimsHash?: string - ): AccessTokenEntity { - const atEntity: AccessTokenEntity = new AccessTokenEntity(); - - atEntity.homeAccountId = homeAccountId; - atEntity.credentialType = CredentialType.ACCESS_TOKEN; - atEntity.secret = accessToken; - - const currentTime = TimeUtils.nowSeconds(); - atEntity.cachedAt = currentTime.toString(); - - /* - * Token expiry time. - * This value should be  calculated based on the current UTC time measured locally and the value  expires_in Represented as a string in JSON. - */ - atEntity.expiresOn = expiresOn.toString(); - atEntity.extendedExpiresOn = extExpiresOn.toString(); - if (refreshOn) { - atEntity.refreshOn = refreshOn.toString(); - } - - atEntity.environment = environment; - atEntity.clientId = clientId; - atEntity.realm = tenantId; - atEntity.target = scopes; - atEntity.userAssertionHash = userAssertionHash; - - atEntity.tokenType = tokenType || AuthenticationScheme.BEARER; - - if (requestedClaims) { - atEntity.requestedClaims = requestedClaims; - atEntity.requestedClaimsHash = requestedClaimsHash; - } - - /* - * Create Access Token With Auth Scheme instead of regular access token - * Cast to lower to handle "bearer" from ADFS - */ - if ( - atEntity.tokenType?.toLowerCase() !== - AuthenticationScheme.BEARER.toLowerCase() - ) { - atEntity.credentialType = - CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; - switch (atEntity.tokenType) { - case AuthenticationScheme.POP: - // Make sure keyId is present and add it to credential - const tokenClaims: TokenClaims | null = extractTokenClaims( - accessToken, - cryptoUtils.base64Decode - ); - if (!tokenClaims?.cnf?.kid) { - throw createClientAuthError( - ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt - ); - } - atEntity.keyId = tokenClaims.cnf.kid; - break; - case AuthenticationScheme.SSH: - atEntity.keyId = keyId; - } - } - - return atEntity; - } - - /** - * Validates an entity: checks for all expected params - * @param entity - */ - static isAccessTokenEntity(entity: object): boolean { - if (!entity) { - return false; - } - - return ( - entity.hasOwnProperty("homeAccountId") && - entity.hasOwnProperty("environment") && - entity.hasOwnProperty("credentialType") && - entity.hasOwnProperty("realm") && - entity.hasOwnProperty("clientId") && - entity.hasOwnProperty("secret") && - entity.hasOwnProperty("target") && - (entity["credentialType"] === CredentialType.ACCESS_TOKEN || - entity["credentialType"] === - CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME) - ); - } -} +}; diff --git a/lib/msal-common/src/cache/entities/CredentialEntity.ts b/lib/msal-common/src/cache/entities/CredentialEntity.ts index 10a40dd2c0..0a224fe4d0 100644 --- a/lib/msal-common/src/cache/entities/CredentialEntity.ts +++ b/lib/msal-common/src/cache/entities/CredentialEntity.ts @@ -3,218 +3,34 @@ * Licensed under the MIT License. */ -import { - Separators, - CredentialType, - CacheType, - Constants, - AuthenticationScheme, -} from "../../utils/Constants"; -import { - ClientAuthErrorCodes, - createClientAuthError, -} from "../../error/ClientAuthError"; +import { CredentialType, AuthenticationScheme } from "../../utils/Constants"; /** - * Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc - * - * Key:Value Schema: - * - * Key: ------- - * - * Value Schema: - * { - * homeAccountId: home account identifier for the auth scheme, - * environment: entity that issued the token, represented as a full host - * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other - * clientId: client ID of the application - * secret: Actual credential as a string - * familyId: Family ID identifier, usually only used for refresh tokens - * realm: Full tenant or organizational identifier that the account belongs to - * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. - * tokenType: Matches the authentication scheme for which the token was issued (i.e. Bearer or pop) - * requestedClaimsHash: Matches the SHA 256 hash of the claims object included in the token request - * userAssertionHash: Matches the SHA 256 hash of the obo_assertion for the OBO flow - * } + * Credential Cache Type */ -export class CredentialEntity { +export type CredentialEntity = { + /** Identifier for the user in their home tenant*/ homeAccountId: string; + /** Entity that issued the token, represented as a full host */ environment: string; + /** Type of credential */ credentialType: CredentialType; + /** Client ID of the application */ clientId: string; + /** Actual credential as a string */ secret: string; + /** Family ID identifier, usually only used for refresh tokens */ familyId?: string; + /** Full tenant or organizational identifier that the account belongs to */ realm?: string; + /** Permissions that are included in the token, or for refresh tokens, the resource identifier. */ target?: string; + /** Matches the SHA 256 hash of the obo_assertion for the OBO flow */ userAssertionHash?: string; + /** Matches the authentication scheme for which the token was issued (i.e. Bearer or pop) */ tokenType?: AuthenticationScheme; + /** KeyId for PoP and SSH tokens stored in the kid claim */ keyId?: string; + /** Matches the SHA 256 hash of the claims object included in the token request */ requestedClaimsHash?: string; - - /** - * Generate Account Id key component as per the schema: - - */ - generateAccountId(): string { - return CredentialEntity.generateAccountIdForCacheKey( - this.homeAccountId, - this.environment - ); - } - - /** - * Generate Credential Id key component as per the schema: -- - */ - generateCredentialId(): string { - return CredentialEntity.generateCredentialIdForCacheKey( - this.credentialType, - this.clientId, - this.realm, - this.familyId - ); - } - - /** - * Generate target key component as per schema: - */ - generateTarget(): string { - return CredentialEntity.generateTargetForCacheKey(this.target); - } - - /** - * generates credential key - */ - generateCredentialKey(): string { - return CredentialEntity.generateCredentialCacheKey( - this.homeAccountId, - this.environment, - this.credentialType, - this.clientId, - this.realm, - this.target, - this.familyId, - this.tokenType, - this.requestedClaimsHash - ); - } - - /** - * returns the type of the cache (in this case credential) - */ - generateType(): number { - switch (this.credentialType) { - case CredentialType.ID_TOKEN: - return CacheType.ID_TOKEN; - case CredentialType.ACCESS_TOKEN: - case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME: - return CacheType.ACCESS_TOKEN; - case CredentialType.REFRESH_TOKEN: - return CacheType.REFRESH_TOKEN; - default: { - throw createClientAuthError( - ClientAuthErrorCodes.unexpectedCredentialType - ); - } - } - } - - /** - * generates credential key - * -\----- - */ - static generateCredentialCacheKey( - homeAccountId: string, - environment: string, - credentialType: CredentialType, - clientId: string, - realm?: string, - target?: string, - familyId?: string, - tokenType?: AuthenticationScheme, - requestedClaimsHash?: string - ): string { - const credentialKey = [ - this.generateAccountIdForCacheKey(homeAccountId, environment), - this.generateCredentialIdForCacheKey( - credentialType, - clientId, - realm, - familyId - ), - this.generateTargetForCacheKey(target), - this.generateClaimsHashForCacheKey(requestedClaimsHash), - this.generateSchemeForCacheKey(tokenType), - ]; - - return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); - } - - /** - * generates Account Id for keys - * @param homeAccountId - * @param environment - */ - private static generateAccountIdForCacheKey( - homeAccountId: string, - environment: string - ): string { - const accountId: Array = [homeAccountId, environment]; - return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); - } - - /** - * Generates Credential Id for keys - * @param credentialType - * @param realm - * @param clientId - * @param familyId - */ - private static generateCredentialIdForCacheKey( - credentialType: CredentialType, - clientId: string, - realm?: string, - familyId?: string - ): string { - const clientOrFamilyId = - credentialType === CredentialType.REFRESH_TOKEN - ? familyId || clientId - : clientId; - const credentialId: Array = [ - credentialType, - clientOrFamilyId, - realm || Constants.EMPTY_STRING, - ]; - - return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); - } - - /** - * Generate target key component as per schema: - */ - private static generateTargetForCacheKey(scopes?: string): string { - return (scopes || Constants.EMPTY_STRING).toLowerCase(); - } - - /** - * Generate requested claims key component as per schema: - */ - private static generateClaimsHashForCacheKey( - requestedClaimsHash?: string - ): string { - return (requestedClaimsHash || Constants.EMPTY_STRING).toLowerCase(); - } - - /** - * Generate scheme key componenet as per schema: - */ - private static generateSchemeForCacheKey(tokenType?: string): string { - /* - * PoP Tokens and SSH certs include scheme in cache key - * Cast to lowercase to handle "bearer" from ADFS - */ - return tokenType && - tokenType.toLowerCase() !== - AuthenticationScheme.BEARER.toLowerCase() - ? tokenType.toLowerCase() - : Constants.EMPTY_STRING; - } -} +}; diff --git a/lib/msal-common/src/cache/entities/IdTokenEntity.ts b/lib/msal-common/src/cache/entities/IdTokenEntity.ts index 03e2ba41e0..300f1bb395 100644 --- a/lib/msal-common/src/cache/entities/IdTokenEntity.ts +++ b/lib/msal-common/src/cache/entities/IdTokenEntity.ts @@ -4,71 +4,11 @@ */ import { CredentialEntity } from "./CredentialEntity"; -import { CredentialType } from "../../utils/Constants"; /** - * ID_TOKEN Cache - * - * Key:Value Schema: - * - * Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com- - * - * Value Schema: - * { - * homeAccountId: home account identifier for the auth scheme, - * environment: entity that issued the token, represented as a full host - * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other - * clientId: client ID of the application - * secret: Actual credential as a string - * realm: Full tenant or organizational identifier that the account belongs to - * } + * Id Token Cache Type */ -export class IdTokenEntity extends CredentialEntity { +export type IdTokenEntity = CredentialEntity & { + /** Full tenant or organizational identifier that the account belongs to */ realm: string; - - /** - * Create IdTokenEntity - * @param homeAccountId - * @param authenticationResult - * @param clientId - * @param authority - */ - static createIdTokenEntity( - homeAccountId: string, - environment: string, - idToken: string, - clientId: string, - tenantId: string - ): IdTokenEntity { - const idTokenEntity = new IdTokenEntity(); - - idTokenEntity.credentialType = CredentialType.ID_TOKEN; - idTokenEntity.homeAccountId = homeAccountId; - idTokenEntity.environment = environment; - idTokenEntity.clientId = clientId; - idTokenEntity.secret = idToken; - idTokenEntity.realm = tenantId; - - return idTokenEntity; - } - - /** - * Validates an entity: checks for all expected params - * @param entity - */ - static isIdTokenEntity(entity: object): boolean { - if (!entity) { - return false; - } - - return ( - entity.hasOwnProperty("homeAccountId") && - entity.hasOwnProperty("environment") && - entity.hasOwnProperty("credentialType") && - entity.hasOwnProperty("realm") && - entity.hasOwnProperty("clientId") && - entity.hasOwnProperty("secret") && - entity["credentialType"] === CredentialType.ID_TOKEN - ); - } -} +}; diff --git a/lib/msal-common/src/cache/entities/RefreshTokenEntity.ts b/lib/msal-common/src/cache/entities/RefreshTokenEntity.ts index e6cfe15c27..0a6bfdad23 100644 --- a/lib/msal-common/src/cache/entities/RefreshTokenEntity.ts +++ b/lib/msal-common/src/cache/entities/RefreshTokenEntity.ts @@ -4,75 +4,8 @@ */ import { CredentialEntity } from "./CredentialEntity"; -import { CredentialType } from "../../utils/Constants"; /** - * REFRESH_TOKEN Cache - * - * Key:Value Schema: - * - * Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId-- - * - * Value: - * { - * homeAccountId: home account identifier for the auth scheme, - * environment: entity that issued the token, represented as a full host - * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other - * clientId: client ID of the application - * secret: Actual credential as a string - * familyId: Family ID identifier, '1' represents Microsoft Family - * realm: Full tenant or organizational identifier that the account belongs to - * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. - * } + * Refresh Token Cache Type */ -export class RefreshTokenEntity extends CredentialEntity { - familyId?: string; - - /** - * Create RefreshTokenEntity - * @param homeAccountId - * @param authenticationResult - * @param clientId - * @param authority - */ - static createRefreshTokenEntity( - homeAccountId: string, - environment: string, - refreshToken: string, - clientId: string, - familyId?: string, - userAssertionHash?: string - ): RefreshTokenEntity { - const rtEntity = new RefreshTokenEntity(); - - rtEntity.clientId = clientId; - rtEntity.credentialType = CredentialType.REFRESH_TOKEN; - rtEntity.environment = environment; - rtEntity.homeAccountId = homeAccountId; - rtEntity.secret = refreshToken; - rtEntity.userAssertionHash = userAssertionHash; - - if (familyId) rtEntity.familyId = familyId; - - return rtEntity; - } - - /** - * Validates an entity: checks for all expected params - * @param entity - */ - static isRefreshTokenEntity(entity: object): boolean { - if (!entity) { - return false; - } - - return ( - entity.hasOwnProperty("homeAccountId") && - entity.hasOwnProperty("environment") && - entity.hasOwnProperty("credentialType") && - entity.hasOwnProperty("clientId") && - entity.hasOwnProperty("secret") && - entity["credentialType"] === CredentialType.REFRESH_TOKEN - ); - } -} +export type RefreshTokenEntity = CredentialEntity; diff --git a/lib/msal-common/src/cache/utils/CacheHelpers.ts b/lib/msal-common/src/cache/utils/CacheHelpers.ts new file mode 100644 index 0000000000..4ef89ce8f3 --- /dev/null +++ b/lib/msal-common/src/cache/utils/CacheHelpers.ts @@ -0,0 +1,306 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { extractTokenClaims } from "../../account/AuthToken"; +import { TokenClaims } from "../../account/TokenClaims"; +import { + ClientAuthErrorCodes, + createClientAuthError, +} from "../../error/ClientAuthError"; +import { + AuthenticationScheme, + CredentialType, + Separators, +} from "../../utils/Constants"; +import { TimeUtils } from "../../utils/TimeUtils"; +import { AccessTokenEntity } from "../entities/AccessTokenEntity"; +import { CredentialEntity } from "../entities/CredentialEntity"; +import { IdTokenEntity } from "../entities/IdTokenEntity"; +import { RefreshTokenEntity } from "../entities/RefreshTokenEntity"; + +/** + * Cache Key: ------- + * IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com + * AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop + * RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com + * @param credentialEntity + * @returns + */ +export function generateCredentialKey( + credentialEntity: CredentialEntity +): string { + const credentialKey = [ + generateAccountId(credentialEntity), + generateCredentialId(credentialEntity), + generateTarget(credentialEntity), + generateClaimsHash(credentialEntity), + generateScheme(credentialEntity), + ]; + + return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); +} + +/** + * Create IdTokenEntity + * @param homeAccountId + * @param authenticationResult + * @param clientId + * @param authority + */ +export function createIdTokenEntity( + homeAccountId: string, + environment: string, + idToken: string, + clientId: string, + tenantId: string +): IdTokenEntity { + const idTokenEntity: IdTokenEntity = { + credentialType: CredentialType.ID_TOKEN, + homeAccountId: homeAccountId, + environment: environment, + clientId: clientId, + secret: idToken, + realm: tenantId, + }; + + return idTokenEntity; +} + +/** + * Create AccessTokenEntity + * @param homeAccountId + * @param environment + * @param accessToken + * @param clientId + * @param tenantId + * @param scopes + * @param expiresOn + * @param extExpiresOn + */ +export function createAccessTokenEntity( + homeAccountId: string, + environment: string, + accessToken: string, + clientId: string, + tenantId: string, + scopes: string, + expiresOn: number, + extExpiresOn: number, + base64Decode: (input: string) => string, + refreshOn?: number, + tokenType?: AuthenticationScheme, + userAssertionHash?: string, + keyId?: string, + requestedClaims?: string, + requestedClaimsHash?: string +): AccessTokenEntity { + const atEntity: AccessTokenEntity = { + homeAccountId: homeAccountId, + credentialType: CredentialType.ACCESS_TOKEN, + secret: accessToken, + cachedAt: TimeUtils.nowSeconds().toString(), + expiresOn: expiresOn.toString(), + extendedExpiresOn: extExpiresOn.toString(), + environment: environment, + clientId: clientId, + realm: tenantId, + target: scopes, + tokenType: tokenType || AuthenticationScheme.BEARER, + }; + + if (userAssertionHash) { + atEntity.userAssertionHash = userAssertionHash; + } + + if (refreshOn) { + atEntity.refreshOn = refreshOn.toString(); + } + + if (requestedClaims) { + atEntity.requestedClaims = requestedClaims; + atEntity.requestedClaimsHash = requestedClaimsHash; + } + + /* + * Create Access Token With Auth Scheme instead of regular access token + * Cast to lower to handle "bearer" from ADFS + */ + if ( + atEntity.tokenType?.toLowerCase() !== + AuthenticationScheme.BEARER.toLowerCase() + ) { + atEntity.credentialType = CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; + switch (atEntity.tokenType) { + case AuthenticationScheme.POP: + // Make sure keyId is present and add it to credential + const tokenClaims: TokenClaims | null = extractTokenClaims( + accessToken, + base64Decode + ); + if (!tokenClaims?.cnf?.kid) { + throw createClientAuthError( + ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt + ); + } + atEntity.keyId = tokenClaims.cnf.kid; + break; + case AuthenticationScheme.SSH: + atEntity.keyId = keyId; + } + } + + return atEntity; +} + +/** + * Create RefreshTokenEntity + * @param homeAccountId + * @param authenticationResult + * @param clientId + * @param authority + */ +export function createRefreshTokenEntity( + homeAccountId: string, + environment: string, + refreshToken: string, + clientId: string, + familyId?: string, + userAssertionHash?: string +): RefreshTokenEntity { + const rtEntity: RefreshTokenEntity = { + credentialType: CredentialType.REFRESH_TOKEN, + homeAccountId: homeAccountId, + environment: environment, + clientId: clientId, + secret: refreshToken, + }; + + if (userAssertionHash) { + rtEntity.userAssertionHash = userAssertionHash; + } + + if (familyId) { + rtEntity.familyId = familyId; + } + + return rtEntity; +} + +export function isCredentialEntity(entity: object): boolean { + return ( + entity.hasOwnProperty("homeAccountId") && + entity.hasOwnProperty("environment") && + entity.hasOwnProperty("credentialType") && + entity.hasOwnProperty("clientId") && + entity.hasOwnProperty("secret") + ); +} + +/** + * Validates an entity: checks for all expected params + * @param entity + */ +export function isAccessTokenEntity(entity: object): boolean { + if (!entity) { + return false; + } + + return ( + isCredentialEntity(entity) && + entity.hasOwnProperty("realm") && + entity.hasOwnProperty("target") && + (entity["credentialType"] === CredentialType.ACCESS_TOKEN || + entity["credentialType"] === + CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME) + ); +} + +/** + * Validates an entity: checks for all expected params + * @param entity + */ +export function isIdTokenEntity(entity: object): boolean { + if (!entity) { + return false; + } + + return ( + isCredentialEntity(entity) && + entity.hasOwnProperty("realm") && + entity["credentialType"] === CredentialType.ID_TOKEN + ); +} + +/** + * Validates an entity: checks for all expected params + * @param entity + */ +export function isRefreshTokenEntity(entity: object): boolean { + if (!entity) { + return false; + } + + return ( + isCredentialEntity(entity) && + entity["credentialType"] === CredentialType.REFRESH_TOKEN + ); +} + +/** + * Generate Account Id key component as per the schema: - + */ +function generateAccountId(credentialEntity: CredentialEntity): string { + const accountId: Array = [ + credentialEntity.homeAccountId, + credentialEntity.environment, + ]; + return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); +} + +/** + * Generate Credential Id key component as per the schema: -- + */ +function generateCredentialId(credentialEntity: CredentialEntity): string { + const clientOrFamilyId = + credentialEntity.credentialType === CredentialType.REFRESH_TOKEN + ? credentialEntity.familyId || credentialEntity.clientId + : credentialEntity.clientId; + const credentialId: Array = [ + credentialEntity.credentialType, + clientOrFamilyId, + credentialEntity.realm || "", + ]; + + return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); +} + +/** + * Generate target key component as per schema: + */ +function generateTarget(credentialEntity: CredentialEntity): string { + return (credentialEntity.target || "").toLowerCase(); +} + +/** + * Generate requested claims key component as per schema: + */ +function generateClaimsHash(credentialEntity: CredentialEntity): string { + return (credentialEntity.requestedClaimsHash || "").toLowerCase(); +} + +/** + * Generate scheme key componenet as per schema: + */ +function generateScheme(credentialEntity: CredentialEntity): string { + /* + * PoP Tokens and SSH certs include scheme in cache key + * Cast to lowercase to handle "bearer" from ADFS + */ + return credentialEntity.tokenType && + credentialEntity.tokenType.toLowerCase() !== + AuthenticationScheme.BEARER.toLowerCase() + ? credentialEntity.tokenType.toLowerCase() + : ""; +} diff --git a/lib/msal-common/src/index.ts b/lib/msal-common/src/index.ts index fb53df6c69..6014327c69 100644 --- a/lib/msal-common/src/index.ts +++ b/lib/msal-common/src/index.ts @@ -71,6 +71,7 @@ export { } from "./cache/utils/CacheTypes"; export { CacheRecord } from "./cache/entities/CacheRecord"; export { CredentialEntity } from "./cache/entities/CredentialEntity"; +export * as CacheHelpers from "./cache/utils/CacheHelpers"; export { AppMetadataEntity } from "./cache/entities/AppMetadataEntity"; export { AccountEntity } from "./cache/entities/AccountEntity"; export { IdTokenEntity } from "./cache/entities/IdTokenEntity"; diff --git a/lib/msal-common/src/response/ResponseHandler.ts b/lib/msal-common/src/response/ResponseHandler.ts index bff1d95a3e..db24b560a2 100644 --- a/lib/msal-common/src/response/ResponseHandler.ts +++ b/lib/msal-common/src/response/ResponseHandler.ts @@ -44,6 +44,7 @@ import { PerformanceEvents } from "../telemetry/performance/PerformanceEvent"; import { checkMaxAge, extractTokenClaims } from "../account/AuthToken"; import { TokenClaims } from "../account/TokenClaims"; import { AccountInfo } from "../account/AccountInfo"; +import * as CacheHelpers from "../cache/utils/CacheHelpers"; /** * Class that handles response parsing. @@ -409,7 +410,7 @@ export class ResponseHandler { let cachedIdToken: IdTokenEntity | undefined; let cachedAccount: AccountEntity | undefined; if (serverTokenResponse.id_token && !!idTokenClaims) { - cachedIdToken = IdTokenEntity.createIdTokenEntity( + cachedIdToken = CacheHelpers.createIdTokenEntity( this.homeAccountIdentifier, env, serverTokenResponse.id_token, @@ -462,16 +463,16 @@ export class ResponseHandler { : undefined; // non AAD scenarios can have empty realm - cachedAccessToken = AccessTokenEntity.createAccessTokenEntity( + cachedAccessToken = CacheHelpers.createAccessTokenEntity( this.homeAccountIdentifier, env, - serverTokenResponse.access_token || Constants.EMPTY_STRING, + serverTokenResponse.access_token, this.clientId, idTokenClaims?.tid || authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, - this.cryptoObj, + this.cryptoObj.base64Decode, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, @@ -484,10 +485,10 @@ export class ResponseHandler { // refreshToken let cachedRefreshToken: RefreshTokenEntity | null = null; if (serverTokenResponse.refresh_token) { - cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity( + cachedRefreshToken = CacheHelpers.createRefreshTokenEntity( this.homeAccountIdentifier, env, - serverTokenResponse.refresh_token || Constants.EMPTY_STRING, + serverTokenResponse.refresh_token, this.clientId, serverTokenResponse.foci, userAssertionHash diff --git a/lib/msal-common/test/cache/CacheManager.spec.ts b/lib/msal-common/test/cache/CacheManager.spec.ts index 50fe7dd0a6..dcf06d9102 100644 --- a/lib/msal-common/test/cache/CacheManager.spec.ts +++ b/lib/msal-common/test/cache/CacheManager.spec.ts @@ -36,7 +36,7 @@ import { AuthorityMetadataEntity } from "../../src/cache/entities/AuthorityMetad import { AppMetadataEntity } from "../../src/cache/entities/AppMetadataEntity"; import { RefreshTokenEntity } from "../../src/cache/entities/RefreshTokenEntity"; import { IdTokenEntity } from "../../src/cache/entities/IdTokenEntity"; -import { CommonSilentFlowRequest, ScopeSet } from "../../src"; +import { CacheHelpers, CommonSilentFlowRequest, ScopeSet } from "../../src"; import * as authorityMetadata from "../../src/authority/AuthorityMetadata"; describe("CacheManager.ts test cases", () => { @@ -96,11 +96,10 @@ describe("CacheManager.ts test cases", () => { }); it("save accessToken", async () => { - const at = new AccessTokenEntity(); - Object.assign(at, { + const at = { homeAccountId: "someUid.someUtid", environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, clientId: "mock_client_id", secret: "an access token sample", realm: "microsoft", @@ -108,10 +107,10 @@ describe("CacheManager.ts test cases", () => { cachedAt: "1000", expiresOn: "4600", extendedExpiresOn: "4600", - tokenType: "Bearer", - }); + tokenType: AuthenticationScheme.BEARER, + }; - const atKey = at.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(at); const cacheRecord = new CacheRecord(); cacheRecord.accessToken = at; await mockCache.cacheManager.saveCacheRecord(cacheRecord); @@ -131,7 +130,7 @@ describe("CacheManager.ts test cases", () => { }); it("does not save accessToken if storeInCache.accessToken = false", async () => { - const at = AccessTokenEntity.createAccessTokenEntity( + const at = CacheHelpers.createAccessTokenEntity( TEST_ACCOUNT_INFO.homeAccountId, TEST_ACCOUNT_INFO.environment, TEST_TOKENS.ACCESS_TOKEN, @@ -140,10 +139,10 @@ describe("CacheManager.ts test cases", () => { "User.Read", TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP, TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP, - mockCrypto + mockCrypto.base64Decode ); - const atKey = at.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(at); const cacheRecord = new CacheRecord(); cacheRecord.accessToken = at; await mockCache.cacheManager.saveCacheRecord(cacheRecord, { @@ -155,11 +154,10 @@ describe("CacheManager.ts test cases", () => { }); it("save accessToken with Auth Scheme (pop)", async () => { - const at = new AccessTokenEntity(); - Object.assign(at, { + const at = { homeAccountId: "someUid.someUtid", environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, clientId: "mock_client_id", secret: "an access token sample", realm: "microsoft", @@ -168,10 +166,10 @@ describe("CacheManager.ts test cases", () => { expiresOn: "4600", extendedExpiresOn: "4600", keyId: "some_key", - tokenType: "pop", - }); + tokenType: AuthenticationScheme.POP, + }; - const atKey = at.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(at); const cacheRecord = new CacheRecord(); cacheRecord.accessToken = at; await mockCache.cacheManager.saveCacheRecord(cacheRecord); @@ -192,7 +190,7 @@ describe("CacheManager.ts test cases", () => { }); it("does not save idToken if storeInCache.idToken = false", async () => { - const idToken = IdTokenEntity.createIdTokenEntity( + const idToken = CacheHelpers.createIdTokenEntity( TEST_ACCOUNT_INFO.homeAccountId, TEST_ACCOUNT_INFO.environment, TEST_TOKENS.IDTOKEN_V2_NEWCLAIM, @@ -200,7 +198,7 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.MSAL_TENANT_ID ); - const idTokenKey = idToken.generateCredentialKey(); + const idTokenKey = CacheHelpers.generateCredentialKey(idToken); const cacheRecord = new CacheRecord(); cacheRecord.idToken = idToken; await mockCache.cacheManager.saveCacheRecord(cacheRecord, { @@ -214,7 +212,7 @@ describe("CacheManager.ts test cases", () => { it("getIdToken matches multiple tokens, removes them and returns null", async () => { await mockCache.cacheManager.clear(); - const idToken1 = IdTokenEntity.createIdTokenEntity( + const idToken1 = CacheHelpers.createIdTokenEntity( TEST_ACCOUNT_INFO.homeAccountId, TEST_ACCOUNT_INFO.environment, TEST_TOKENS.IDTOKEN_V2, @@ -222,7 +220,7 @@ describe("CacheManager.ts test cases", () => { TEST_ACCOUNT_INFO.tenantId ); - const idToken2 = IdTokenEntity.createIdTokenEntity( + const idToken2 = CacheHelpers.createIdTokenEntity( TEST_ACCOUNT_INFO.homeAccountId, TEST_ACCOUNT_INFO.environment, TEST_TOKENS.IDTOKEN_V2_NEWCLAIM, @@ -246,14 +244,15 @@ describe("CacheManager.ts test cases", () => { }); it("does not save refreshToken if storeInCache.refreshToken = false", async () => { - const refreshToken = RefreshTokenEntity.createRefreshTokenEntity( + const refreshToken = CacheHelpers.createRefreshTokenEntity( TEST_ACCOUNT_INFO.homeAccountId, TEST_ACCOUNT_INFO.environment, TEST_TOKENS.REFRESH_TOKEN, TEST_CONFIG.MSAL_CLIENT_ID ); - const refreshTokenKey = refreshToken.generateCredentialKey(); + const refreshTokenKey = + CacheHelpers.generateCredentialKey(refreshToken); const cacheRecord = new CacheRecord(); cacheRecord.refreshToken = refreshToken; await mockCache.cacheManager.saveCacheRecord(cacheRecord, { @@ -297,15 +296,19 @@ describe("CacheManager.ts test cases", () => { }); it("getAccessTokenCredential (Bearer)", async () => { - const accessTokenEntity = new AccessTokenEntity(); - accessTokenEntity.homeAccountId = "someUid.someUtid"; - accessTokenEntity.environment = "login.microsoftonline.com"; - accessTokenEntity.realm = "microsoft"; - accessTokenEntity.clientId = "mock_client_id"; - accessTokenEntity.credentialType = CredentialType.ACCESS_TOKEN; - accessTokenEntity.target = "scope6 scope7"; - - const credKey = accessTokenEntity.generateCredentialKey(); + const accessTokenEntity: AccessTokenEntity = { + homeAccountId: "someUid.someUtid", + environment: "login.microsoftonline.com", + realm: "microsoft", + clientId: "mock_client_id", + credentialType: CredentialType.ACCESS_TOKEN, + target: "scope6 scope7", + secret: TEST_TOKENS.ACCESS_TOKEN, + cachedAt: "1000", + expiresOn: "4600", + }; + + const credKey = CacheHelpers.generateCredentialKey(accessTokenEntity); const cacheRecord = new CacheRecord(); cacheRecord.accessToken = accessTokenEntity; await mockCache.cacheManager.saveCacheRecord(cacheRecord); @@ -321,16 +324,19 @@ describe("CacheManager.ts test cases", () => { }); it("getAccessTokenCredential (POP)", async () => { - const accessTokenEntity = new AccessTokenEntity(); - accessTokenEntity.homeAccountId = "someUid.someUtid"; - accessTokenEntity.environment = "login.microsoftonline.com"; - accessTokenEntity.realm = "microsoft"; - accessTokenEntity.clientId = "mock_client_id"; - accessTokenEntity.credentialType = - CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; - accessTokenEntity.target = "scope6 scope7"; - - const credKey = accessTokenEntity.generateCredentialKey(); + const accessTokenEntity: AccessTokenEntity = { + homeAccountId: "someUid.someUtid", + environment: "login.microsoftonline.com", + realm: "microsoft", + clientId: "mock_client_id", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, + target: "scope6 scope7", + secret: TEST_TOKENS.ACCESS_TOKEN, + cachedAt: "1000", + expiresOn: "4600", + }; + + const credKey = CacheHelpers.generateCredentialKey(accessTokenEntity); const cacheRecord = new CacheRecord(); cacheRecord.accessToken = accessTokenEntity; await mockCache.cacheManager.saveCacheRecord(cacheRecord); @@ -1154,11 +1160,10 @@ describe("CacheManager.ts test cases", () => { }); it("removeAccessToken", async () => { - const at = new AccessTokenEntity(); - Object.assign(at, { + const at = { homeAccountId: "someUid.someUtid", environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, clientId: "mock_client_id", secret: "an access token sample", realm: "microsoft", @@ -1166,20 +1171,19 @@ describe("CacheManager.ts test cases", () => { cachedAt: "1000", expiresOn: "4600", extendedExpiresOn: "4600", - }); + }; await mockCache.cacheManager.removeAccessToken( - at.generateCredentialKey() + CacheHelpers.generateCredentialKey(at) ); - const atKey = at.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(at); expect(mockCache.cacheManager.getAccount(atKey)).toBeNull(); }); it("removes token binding key when removeAccessToken is called for a PoP AccessToken_With_AuthScheme credential", async () => { - const atWithAuthScheme = new AccessTokenEntity(); - const atWithAuthSchemeData = { + const atWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an access token", realm: "microsoft", target: "scope1 scope2 scope3", @@ -1197,23 +1201,20 @@ describe("CacheManager.ts test cases", () => { "removeTokenBindingKey" ); - Object.assign(atWithAuthScheme, atWithAuthSchemeData); - await mockCache.cacheManager.removeAccessToken( - atWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey(atWithAuthScheme) ); - const atKey = atWithAuthScheme.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(atWithAuthScheme); expect(mockCache.cacheManager.getAccount(atKey)).toBeNull(); expect(removeTokenBindingKeySpy.getCall(0).args[0]).toEqual( - atWithAuthSchemeData.keyId + atWithAuthScheme.keyId ); }); it("does not try to remove binding key when removeAccessToken is called for an SSH AccessToken_With_AuthScheme credential", async () => { - const atWithAuthScheme = new AccessTokenEntity(); - const atWithAuthSchemeData = { + const atWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an SSH Cert", realm: "microsoft", target: "scope1 scope2 scope3", @@ -1231,21 +1232,18 @@ describe("CacheManager.ts test cases", () => { "removeTokenBindingKey" ); - Object.assign(atWithAuthScheme, atWithAuthSchemeData); - await mockCache.cacheManager.removeAccessToken( - atWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey(atWithAuthScheme) ); - const atKey = atWithAuthScheme.generateCredentialKey(); + const atKey = CacheHelpers.generateCredentialKey(atWithAuthScheme); expect(mockCache.cacheManager.getAccount(atKey)).toBeNull(); expect(removeTokenBindingKeySpy.callCount).toEqual(0); }); it("throws bindingKeyNotRemoved error when key isn't deleted from storage", async () => { - const atWithAuthScheme = new AccessTokenEntity(); - const atWithAuthSchemeData = { + const atWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an access token", realm: "microsoft", target: "scope1 scope2 scope3", @@ -1255,11 +1253,9 @@ describe("CacheManager.ts test cases", () => { extendedExpiresOn: "4600", expiresOn: "4600", keyId: "V6N_HMPagNpYS_wxM14X73q3eWzbTr9Z31RyHkIcN0Y", - tokenType: "pop", + tokenType: AuthenticationScheme.POP, }; - Object.assign(atWithAuthScheme, atWithAuthSchemeData); - jest.spyOn(mockCrypto, "removeTokenBindingKey").mockImplementation( (keyId: string): Promise => { return Promise.reject(); @@ -1268,7 +1264,7 @@ describe("CacheManager.ts test cases", () => { return await expect( mockCache.cacheManager.removeAccessToken( - atWithAuthScheme.generateCredentialKey() + CacheHelpers.generateCredentialKey(atWithAuthScheme) ) ).rejects.toThrow( createClientAuthError(ClientAuthErrorCodes.bindingKeyNotRemoved) @@ -1279,7 +1275,7 @@ describe("CacheManager.ts test cases", () => { await mockCache.cacheManager.clear(); const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "an_access_token", @@ -1288,14 +1284,14 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN ); const mockedAtEntity2: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "an_access_token", @@ -1304,7 +1300,7 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN @@ -1361,7 +1357,7 @@ describe("CacheManager.ts test cases", () => { it("getAccessToken only matches a Bearer Token when Authentication Scheme is set to Bearer", () => { const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "access_token", @@ -1370,14 +1366,14 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN ); const mockedPopAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.POP_TOKEN, @@ -1386,14 +1382,14 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.POP, TEST_TOKENS.ACCESS_TOKEN ); const mockedSshAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.SSH_CERTIFICATE, @@ -1402,7 +1398,7 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.SSH, undefined, @@ -1454,7 +1450,7 @@ describe("CacheManager.ts test cases", () => { it("getAccessToken matches a Bearer Token when Authentication Scheme is set to bearer (lowercase from adfs)", () => { const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "access_token", @@ -1463,7 +1459,7 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, // @ts-ignore AuthenticationScheme.BEARER.toLowerCase(), @@ -1514,7 +1510,7 @@ describe("CacheManager.ts test cases", () => { it("getAccessToken only matches a POP Token when Authentication Scheme is set to pop", () => { const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "access_token", @@ -1523,14 +1519,14 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN ); const mockedPopAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.POP_TOKEN, @@ -1539,14 +1535,14 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.POP, TEST_TOKENS.ACCESS_TOKEN ); const mockedSshAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.SSH_CERTIFICATE, @@ -1555,7 +1551,7 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.SSH, undefined, @@ -1608,7 +1604,7 @@ describe("CacheManager.ts test cases", () => { it("getAccessToken only matches an SSH Certificate when Authentication Scheme is set to ssh-cert", () => { const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", "access_token", @@ -1617,7 +1613,7 @@ describe("CacheManager.ts test cases", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.BEARER, undefined, @@ -1625,7 +1621,7 @@ describe("CacheManager.ts test cases", () => { ); const mockedPopAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.POP_TOKEN, @@ -1634,7 +1630,7 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.POP, undefined, @@ -1642,7 +1638,7 @@ describe("CacheManager.ts test cases", () => { ); const mockedSshAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "uid.utid", "login.microsoftonline.com", TEST_TOKENS.SSH_CERTIFICATE, @@ -1651,7 +1647,7 @@ describe("CacheManager.ts test cases", () => { "User.Read test_scope", 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, 500, AuthenticationScheme.SSH, undefined, diff --git a/lib/msal-common/test/cache/MockCache.ts b/lib/msal-common/test/cache/MockCache.ts index 49f6f1d230..455ec18c27 100644 --- a/lib/msal-common/test/cache/MockCache.ts +++ b/lib/msal-common/test/cache/MockCache.ts @@ -4,16 +4,16 @@ */ import { - AccessTokenEntity, AccountEntity, AppMetadataEntity, AuthorityMetadataEntity, CacheManager, ICrypto, - IdTokenEntity, RefreshTokenEntity, Logger, StaticAuthorityOptions, + CredentialType, + AuthenticationScheme, } from "../../src"; import { MockStorageClass } from "../client/ClientTestUtils"; import { TEST_TOKENS, TEST_CRYPTO_VALUES } from "../test_kit/StringConstants"; @@ -120,23 +120,22 @@ export class MockCache { // create id token entries in the cache createIdTokenEntries(): void { - const idTokenData = { + const idToken = { realm: "microsoft", environment: "login.microsoftonline.com", - credentialType: "IdToken", + credentialType: CredentialType.ID_TOKEN, secret: TEST_TOKENS.IDTOKEN_V2, clientId: "mock_client_id", homeAccountId: "uid.utid", }; - const idToken = CacheManager.toObject(new IdTokenEntity(), idTokenData); this.cacheManager.setIdTokenCredential(idToken); } // create access token entries in the cache createAccessTokenEntries(): void { - const atOneData = { + const atOne = { environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, secret: "an access token", realm: "microsoft", target: "scope1 scope2 scope3", @@ -145,14 +144,13 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "Bearer", + tokenType: AuthenticationScheme.BEARER, }; - const atOne = CacheManager.toObject(new AccessTokenEntity(), atOneData); this.cacheManager.setAccessTokenCredential(atOne); - const atTwoData = { + const atTwo = { environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, secret: "an access token", realm: "microsoft", target: "scope4 scope5", @@ -161,15 +159,14 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "Bearer", + tokenType: AuthenticationScheme.BEARER, }; - const atTwo = CacheManager.toObject(new AccessTokenEntity(), atTwoData); this.cacheManager.setAccessTokenCredential(atTwo); // With requested claims - const atThreeData = { + const atThree = { environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, secret: "an access token", realm: "microsoft", target: "scope4 scope5", @@ -178,21 +175,17 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "Bearer", + tokenType: AuthenticationScheme.BEARER, requestedClaims: JSON.stringify({ claim: "claim" }), requestedClaimsHash: TEST_CRYPTO_VALUES.TEST_SHA256_HASH, }; - const atThree = CacheManager.toObject( - new AccessTokenEntity(), - atThreeData - ); this.cacheManager.setAccessTokenCredential(atThree); // BEARER with AuthScheme Token - const bearerAtWithAuthSchemeData = { + const bearerAtWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an access token", realm: "microsoft", target: "scope1 scope2 scope3", @@ -201,18 +194,14 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "Bearer", + tokenType: AuthenticationScheme.BEARER, }; - const bearerAtWithAuthScheme = CacheManager.toObject( - new AccessTokenEntity(), - bearerAtWithAuthSchemeData - ); this.cacheManager.setAccessTokenCredential(bearerAtWithAuthScheme); // POP Token - const popAtWithAuthSchemeData = { + const popAtWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an access token", realm: "microsoft", target: "scope1 scope2 scope3", @@ -221,19 +210,15 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "pop", + tokenType: AuthenticationScheme.POP, keyId: "V6N_HMPagNpYS_wxM14X73q3eWzbTr9Z31RyHkIcN0Y", }; - const popAtWithAuthScheme = CacheManager.toObject( - new AccessTokenEntity(), - popAtWithAuthSchemeData - ); this.cacheManager.setAccessTokenCredential(popAtWithAuthScheme); // SSH Certificate - const sshAtWithAuthSchemeData = { + const sshAtWithAuthScheme = { environment: "login.microsoftonline.com", - credentialType: "AccessToken_With_AuthScheme", + credentialType: CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME, secret: "an SSH Cert", realm: "microsoft", target: "scope1 scope2 scope3", @@ -242,19 +227,15 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "ssh-cert", + tokenType: AuthenticationScheme.SSH, keyId: "some_key_id", }; - const sshAtWithAuthScheme = CacheManager.toObject( - new AccessTokenEntity(), - sshAtWithAuthSchemeData - ); this.cacheManager.setAccessTokenCredential(sshAtWithAuthScheme); // userAssertionHash - const atWithUserAssertionHashData = { + const atWithUserAssertionHash = { environment: "login.microsoftonline.com", - credentialType: "AccessToken", + credentialType: CredentialType.ACCESS_TOKEN, secret: "an SSH Cert", realm: "microsoft", target: "scope1 scope2 scope3", @@ -263,40 +244,31 @@ export class MockCache { homeAccountId: "uid.utid", extendedExpiresOn: "4600", expiresOn: "4600", - tokenType: "ssh-cert", + tokenType: AuthenticationScheme.SSH, userAssertionHash: "nFDCbX7CudvdluSPGh34Y-VKZIXRG1rquljNBbn7xuE", }; - const atWithUserAssertionHash = CacheManager.toObject( - new AccessTokenEntity(), - atWithUserAssertionHashData - ); this.cacheManager.setAccessTokenCredential(atWithUserAssertionHash); } // create refresh token entries in the cache createRefreshTokenEntries(): void { - const rtData = { + const rt: RefreshTokenEntity = { environment: "login.microsoftonline.com", - credentialType: "RefreshToken", + credentialType: CredentialType.REFRESH_TOKEN, secret: "a refresh token", clientId: "mock_client_id", homeAccountId: "uid.utid", }; - const rt = CacheManager.toObject(new RefreshTokenEntity(), rtData); this.cacheManager.setRefreshTokenCredential(rt); - const rtFociData = { + const rtFoci = { environment: "login.microsoftonline.com", - credentialType: "RefreshToken", + credentialType: CredentialType.REFRESH_TOKEN, secret: "a refresh token", clientId: "mock_client_id", homeAccountId: "uid.utid", familyId: "1", }; - const rtFoci = CacheManager.toObject( - new RefreshTokenEntity(), - rtFociData - ); this.cacheManager.setRefreshTokenCredential(rtFoci); } diff --git a/lib/msal-common/test/cache/entities/AccessTokenEntity.spec.ts b/lib/msal-common/test/cache/entities/AccessTokenEntity.spec.ts index fca5a9ddfd..b17a21d584 100644 --- a/lib/msal-common/test/cache/entities/AccessTokenEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/AccessTokenEntity.spec.ts @@ -1,4 +1,3 @@ -import { AccessTokenEntity } from "../../../src/cache/entities/AccessTokenEntity"; import { mockCache, mockAccessTokenEntity_1, @@ -6,83 +5,51 @@ import { mockRefreshTokenEntity, mockAccessTokenWithAuthSchemeEntity, } from "./cacheConstants"; -import { CacheType } from "../../../src/utils/Constants"; -import { - ClientAuthError, - ClientAuthErrorMessage, -} from "../../../src/error/ClientAuthError"; +import { CacheHelpers } from "../../../src"; describe("AccessTokenEntity.ts Unit Tests", () => { describe("AccessToken Credential entity", () => { - it("Verify an AccessTokenEntity entity", () => { - const at = new AccessTokenEntity(); - expect(at instanceof AccessTokenEntity); - }); - it("Generate AccessTokenEntity key", () => { const at = mockCache.createMockATOne(); - expect(at.generateCredentialKey()).toEqual( + expect(CacheHelpers.generateCredentialKey(at)).toEqual( "uid.utid-login.microsoftonline.com-accesstoken-mock_client_id-microsoft-scope1 scope2 scope3--" ); }); it("Generate AccessTokenEntity key (adfs)", () => { const at = mockCache.createMockAdfsAt(); - expect(at.generateCredentialKey()).toEqual( + expect(CacheHelpers.generateCredentialKey(at)).toEqual( "uid.utid-login.microsoftonline.com-accesstoken-mock_client_id-microsoft-scope1 scope2 scope3--" ); }); - it("Throws error if AccessTokenEntity is not assigned a type", () => { - const at = new AccessTokenEntity(); - expect(() => at.generateType()).toThrowError(ClientAuthError); - expect(() => at.generateType()).toThrowError( - ClientAuthErrorMessage.unexpectedCredentialType.desc - ); - }); - - it("Generate AccessTokenEntity type", () => { - const at = mockCache.createMockATOne(); - expect(at.generateType()).toEqual(CacheType.ACCESS_TOKEN); - }); - it("verify if an object is an access token entity", () => { expect( - AccessTokenEntity.isAccessTokenEntity(mockAccessTokenEntity_1) + CacheHelpers.isAccessTokenEntity(mockAccessTokenEntity_1) ).toEqual(true); expect( - AccessTokenEntity.isAccessTokenEntity(mockAccessTokenEntity_2) + CacheHelpers.isAccessTokenEntity(mockAccessTokenEntity_2) ).toEqual(true); }); it("verify if an object is not an access token entity", () => { expect( - AccessTokenEntity.isAccessTokenEntity(mockRefreshTokenEntity) + CacheHelpers.isAccessTokenEntity(mockRefreshTokenEntity) ).toEqual(false); }); }); describe("AccessToken_With_AuthScheme credential entity", () => { - it("Verify an AccessToken_With_AuthScheme entity", () => { - const popAT = mockCache.createMockPopAT(); - expect(popAT instanceof AccessTokenEntity); - }); - it("Generate AccessTokenEntity key", () => { const popAT = mockCache.createMockPopAT(); - expect(popAT.generateCredentialKey()).toEqual( + expect(CacheHelpers.generateCredentialKey(popAT)).toEqual( "uid.utid-login.microsoftonline.com-accesstoken_with_authscheme-mock_client_id-microsoft-scope1 scope2 scope3--pop" ); }); - it("Generate AccessTokenEntity type", () => { - const popAT = mockCache.createMockPopAT(); - expect(popAT.generateType()).toEqual(CacheType.ACCESS_TOKEN); - }); - it("verify if an object is an access token entity", () => { expect( - AccessTokenEntity.isAccessTokenEntity( + CacheHelpers.isAccessTokenEntity( mockAccessTokenWithAuthSchemeEntity ) ).toEqual(true); diff --git a/lib/msal-common/test/cache/entities/AppMetadataEntity.spec.ts b/lib/msal-common/test/cache/entities/AppMetadataEntity.spec.ts index ea9a4926db..b59ec0607e 100644 --- a/lib/msal-common/test/cache/entities/AppMetadataEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/AppMetadataEntity.spec.ts @@ -1,6 +1,7 @@ import { AppMetadataEntity } from "../../../src/cache/entities/AppMetadataEntity"; import { mockAppMetaDataEntity, mockIdTokenEntity } from "./cacheConstants"; import { IdTokenEntity } from "../../../src/cache/entities/IdTokenEntity"; +import { CacheHelpers } from "../../../src"; describe("AppMetadataEntity.ts Unit Tests", () => { it("Verify an AppMetadataEntity", () => { @@ -26,9 +27,9 @@ describe("AppMetadataEntity.ts Unit Tests", () => { }); it("verify if an object is not an appMetadata entity", () => { - const idT = new IdTokenEntity(); - Object.assign(idT, mockIdTokenEntity); - const key = idT.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey( + mockIdTokenEntity as IdTokenEntity + ); expect( AppMetadataEntity.isAppMetadataEntity(key, mockIdTokenEntity) ).toEqual(false); diff --git a/lib/msal-common/test/cache/entities/IdTokenEntity.spec.ts b/lib/msal-common/test/cache/entities/IdTokenEntity.spec.ts index b19d244619..fb568f5861 100644 --- a/lib/msal-common/test/cache/entities/IdTokenEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/IdTokenEntity.spec.ts @@ -1,45 +1,19 @@ -import { IdTokenEntity } from "../../../src/cache/entities/IdTokenEntity"; import { mockIdTokenEntity, mockAccessTokenEntity_1 } from "./cacheConstants"; -import { CacheType } from "../../../src/utils/Constants"; -import { - ClientAuthError, - ClientAuthErrorMessage, -} from "../../../src/error/ClientAuthError"; +import { CacheHelpers } from "../../../src"; describe("IdTokenEntity.ts Unit Tests", () => { - it("Verify an IdTokenEntity", () => { - const idT = new IdTokenEntity(); - expect(idT instanceof IdTokenEntity); - }); - it("Create an IdTokenEntity", () => { - const idT = new IdTokenEntity(); - Object.assign(idT, mockIdTokenEntity); - expect(idT.generateCredentialKey()).toEqual( + expect(CacheHelpers.generateCredentialKey(mockIdTokenEntity)).toEqual( "uid.utid-login.microsoftonline.com-idtoken-mock_client_id-microsoft---" ); }); - it("Throws error if IdTokenEntity is not assigned a type", () => { - const idT = new IdTokenEntity(); - expect(() => idT.generateType()).toThrowError(ClientAuthError); - expect(() => idT.generateType()).toThrowError( - ClientAuthErrorMessage.unexpectedCredentialType.desc - ); - }); - - it("Generate IdTokenEntity type", () => { - const idT = new IdTokenEntity(); - Object.assign(idT, mockIdTokenEntity); - expect(idT.generateType()).toEqual(CacheType.ID_TOKEN); - }); - it("verify if an object is an id token entity", () => { - expect(IdTokenEntity.isIdTokenEntity(mockIdTokenEntity)).toEqual(true); + expect(CacheHelpers.isIdTokenEntity(mockIdTokenEntity)).toEqual(true); }); it("verify if an object is not an id token entity", () => { - expect(IdTokenEntity.isIdTokenEntity(mockAccessTokenEntity_1)).toEqual( + expect(CacheHelpers.isIdTokenEntity(mockAccessTokenEntity_1)).toEqual( false ); }); diff --git a/lib/msal-common/test/cache/entities/RefreshTokenEntity.spec.ts b/lib/msal-common/test/cache/entities/RefreshTokenEntity.spec.ts index 991558f218..0599c9073b 100644 --- a/lib/msal-common/test/cache/entities/RefreshTokenEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/RefreshTokenEntity.spec.ts @@ -1,57 +1,33 @@ -import { RefreshTokenEntity } from "../../../src/cache/entities/RefreshTokenEntity"; import { mockRefreshTokenEntity, mockRefreshTokenEntityWithFamilyId, mockAppMetaDataEntity, } from "./cacheConstants"; -import { CacheType } from "../../../src/utils/Constants"; -import { - ClientAuthError, - ClientAuthErrorMessage, -} from "../../../src/error/ClientAuthError"; +import { CacheHelpers } from "../../../src"; describe("RefreshTokenEntity.ts Unit Tests", () => { - it("Verify a RefreshTokenEntity", () => { - const rt = new RefreshTokenEntity(); - expect(rt instanceof RefreshTokenEntity); - }); - it("Create a RefreshTokenEntity", () => { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntity); - expect(rt.generateCredentialKey()).toEqual( + expect( + CacheHelpers.generateCredentialKey(mockRefreshTokenEntity) + ).toEqual( "uid.utid-login.microsoftonline.com-refreshtoken-mock_client_id----" ); }); it("Create a RefreshTokenEntity with familyId", () => { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntityWithFamilyId); - expect(rt.generateCredentialKey()).toEqual( - "uid.utid-login.microsoftonline.com-refreshtoken-1----" - ); - }); - - it("Throws error if RefreshTokenEntity is not assigned a type", () => { - const rt = new RefreshTokenEntity(); - expect(() => rt.generateType()).toThrowError(ClientAuthError); - expect(() => rt.generateType()).toThrowError( - ClientAuthErrorMessage.unexpectedCredentialType.desc - ); - }); - - it("Generate RefreshTokenEntity type", () => { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntity); - expect(rt.generateType()).toEqual(CacheType.REFRESH_TOKEN); + expect( + CacheHelpers.generateCredentialKey( + mockRefreshTokenEntityWithFamilyId + ) + ).toEqual("uid.utid-login.microsoftonline.com-refreshtoken-1----"); }); it("verify if an object is a refresh token entity", () => { expect( - RefreshTokenEntity.isRefreshTokenEntity(mockRefreshTokenEntity) + CacheHelpers.isRefreshTokenEntity(mockRefreshTokenEntity) ).toEqual(true); expect( - RefreshTokenEntity.isRefreshTokenEntity( + CacheHelpers.isRefreshTokenEntity( mockRefreshTokenEntityWithFamilyId ) ).toEqual(true); @@ -59,7 +35,7 @@ describe("RefreshTokenEntity.ts Unit Tests", () => { it("verify if an object is not a refresh token entity", () => { expect( - RefreshTokenEntity.isRefreshTokenEntity(mockAppMetaDataEntity) + CacheHelpers.isRefreshTokenEntity(mockAppMetaDataEntity) ).toEqual(false); }); }); diff --git a/lib/msal-common/test/cache/entities/cacheConstants.ts b/lib/msal-common/test/cache/entities/cacheConstants.ts index bc7ba6601e..97036c724d 100644 --- a/lib/msal-common/test/cache/entities/cacheConstants.ts +++ b/lib/msal-common/test/cache/entities/cacheConstants.ts @@ -9,9 +9,10 @@ import { RefreshTokenEntity } from "../../../src/cache/entities/RefreshTokenEnti import { AccountEntity } from "../../../src/cache/entities/AccountEntity"; import { AppMetadataEntity } from "../../../src/cache/entities/AppMetadataEntity"; import { AuthenticationScheme } from "../../../src/utils/Constants"; +import { CacheHelpers } from "../../../src"; // mock tokens -export const mockAccessTokenEntity_1 = { +export const mockAccessTokenEntity_1: AccessTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "AccessToken", @@ -24,7 +25,7 @@ export const mockAccessTokenEntity_1 = { extendedExpiresOn: "4600", }; -export const mockAccessTokenEntity_2 = { +export const mockAccessTokenEntity_2: AccessTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "AccessToken", @@ -37,7 +38,7 @@ export const mockAccessTokenEntity_2 = { extendedExpiresOn: "4600", }; -export const mockAccessTokenWithAuthSchemeEntity = { +export const mockAccessTokenWithAuthSchemeEntity: AccessTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "AccessToken_With_AuthScheme", @@ -52,7 +53,7 @@ export const mockAccessTokenWithAuthSchemeEntity = { keyId: "someKeyId123", }; -export const mockIdTokenEntity = { +export const mockIdTokenEntity: IdTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "IdToken", @@ -61,7 +62,7 @@ export const mockIdTokenEntity = { realm: "microsoft", }; -export const mockRefreshTokenEntity = { +export const mockRefreshTokenEntity: RefreshTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "RefreshToken", @@ -69,7 +70,7 @@ export const mockRefreshTokenEntity = { secret: "a refresh token", }; -export const mockRefreshTokenEntityWithFamilyId = { +export const mockRefreshTokenEntityWithFamilyId: RefreshTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "RefreshToken", @@ -97,22 +98,15 @@ export const mockAppMetaDataEntity = { // generate mockCache export class mockCache { static createMockATOne(): AccessTokenEntity { - const at = new AccessTokenEntity(); - Object.assign(at, mockAccessTokenEntity_1); - - return at; + return mockAccessTokenEntity_1; } static createMockATTwo(): AccessTokenEntity { - const at = new AccessTokenEntity(); - Object.assign(at, mockAccessTokenEntity_2); - - return at; + return mockAccessTokenEntity_2; } static createMockAdfsAt(): AccessTokenEntity { - const at = new AccessTokenEntity(); - Object.assign(at, mockAccessTokenEntity_1); + const at = { ...mockAccessTokenEntity_1 }; // @ts-ignore at.tokenType = AuthenticationScheme.BEARER.toLowerCase(); // ADFS may return type as "bearer" (lowercase) @@ -121,31 +115,19 @@ export class mockCache { } static createMockPopAT(): AccessTokenEntity { - const popAt = new AccessTokenEntity(); - Object.assign(popAt, mockAccessTokenWithAuthSchemeEntity); - - return popAt; + return mockAccessTokenWithAuthSchemeEntity; } static createMockIdT(): IdTokenEntity { - const idt = new IdTokenEntity(); - Object.assign(idt, mockIdTokenEntity); - - return idt; + return mockIdTokenEntity; } static createMockRT(): RefreshTokenEntity { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntity); - - return rt; + return mockRefreshTokenEntity; } static createMockRTWithFamilyId(): RefreshTokenEntity { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntityWithFamilyId); - - return rt; + return mockRefreshTokenEntityWithFamilyId; } static createMockAcc(): AccountEntity { @@ -165,16 +147,18 @@ export class mockCache { export const MockCache = { atOne: mockCache.createMockATOne(), - atOneKey: mockCache.createMockATOne().generateCredentialKey(), + atOneKey: CacheHelpers.generateCredentialKey(mockCache.createMockATOne()), atTwo: mockCache.createMockATTwo(), - atTwoKey: mockCache.createMockATTwo().generateCredentialKey(), + atTwoKey: CacheHelpers.generateCredentialKey(mockCache.createMockATTwo()), popAt: mockCache.createMockPopAT(), idT: mockCache.createMockIdT(), - idTKey: mockCache.createMockIdT().generateCredentialKey(), + idTKey: CacheHelpers.generateCredentialKey(mockCache.createMockIdT()), rt: mockCache.createMockRT(), - rtKey: mockCache.createMockRT().generateCredentialKey(), + rtKey: CacheHelpers.generateCredentialKey(mockCache.createMockRT()), rtF: mockCache.createMockRTWithFamilyId(), - rtFKey: mockCache.createMockRTWithFamilyId().generateCredentialKey(), + rtFKey: CacheHelpers.generateCredentialKey( + mockCache.createMockRTWithFamilyId() + ), acc: mockCache.createMockAcc(), accKey: mockCache.createMockAcc().generateAccountKey(), amdt: mockCache.createMockAmdt(), diff --git a/lib/msal-common/test/client/ClientTestUtils.ts b/lib/msal-common/test/client/ClientTestUtils.ts index 948d2c9eaf..a5ac01ff15 100644 --- a/lib/msal-common/test/client/ClientTestUtils.ts +++ b/lib/msal-common/test/client/ClientTestUtils.ts @@ -23,6 +23,7 @@ import { ServerTelemetryManager, createClientAuthError, ClientAuthErrorCodes, + CacheHelpers, } from "../../src"; import { RANDOM_TEST_GUID, @@ -89,7 +90,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as IdTokenEntity) || null; } setIdTokenCredential(value: IdTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -104,7 +105,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as AccessTokenEntity) || null; } setAccessTokenCredential(value: AccessTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -119,7 +120,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as RefreshTokenEntity) || null; } setRefreshTokenCredential(value: RefreshTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -194,7 +195,7 @@ export class MockStorageClass extends CacheManager { currentCacheKey: string, credential: ValidCredentialType ): string { - const updatedCacheKey = credential.generateCredentialKey(); + const updatedCacheKey = CacheHelpers.generateCredentialKey(credential); if (currentCacheKey !== updatedCacheKey) { const cacheItem = this.store[currentCacheKey]; diff --git a/lib/msal-common/test/client/RefreshTokenClient.spec.ts b/lib/msal-common/test/client/RefreshTokenClient.spec.ts index d16154a2ba..9c3f758ba9 100644 --- a/lib/msal-common/test/client/RefreshTokenClient.spec.ts +++ b/lib/msal-common/test/client/RefreshTokenClient.spec.ts @@ -70,23 +70,24 @@ const testAppMetadata: AppMetadataEntity = new AppMetadataEntity(); testAppMetadata.clientId = TEST_CONFIG.MSAL_CLIENT_ID; testAppMetadata.familyId = TEST_CONFIG.THE_FAMILY_ID; -const testRefreshTokenEntity: RefreshTokenEntity = new RefreshTokenEntity(); -testRefreshTokenEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testRefreshTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testRefreshTokenEntity.environment = testAccountEntity.environment; -testRefreshTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testRefreshTokenEntity.secret = AUTHENTICATION_RESULT.body.refresh_token; -testRefreshTokenEntity.credentialType = CredentialType.REFRESH_TOKEN; - -const testFamilyRefreshTokenEntity: RefreshTokenEntity = - new RefreshTokenEntity(); -testFamilyRefreshTokenEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testFamilyRefreshTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testFamilyRefreshTokenEntity.environment = testAccountEntity.environment; -testFamilyRefreshTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testFamilyRefreshTokenEntity.secret = AUTHENTICATION_RESULT.body.refresh_token; -testFamilyRefreshTokenEntity.credentialType = CredentialType.REFRESH_TOKEN; -testFamilyRefreshTokenEntity.familyId = TEST_CONFIG.THE_FAMILY_ID; +const testRefreshTokenEntity: RefreshTokenEntity = { + homeAccountId: `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: AUTHENTICATION_RESULT.body.refresh_token, + credentialType: CredentialType.REFRESH_TOKEN, +}; + +const testFamilyRefreshTokenEntity: RefreshTokenEntity = { + homeAccountId: `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: AUTHENTICATION_RESULT.body.refresh_token, + credentialType: CredentialType.REFRESH_TOKEN, + familyId: TEST_CONFIG.THE_FAMILY_ID, +}; describe("RefreshTokenClient unit tests", () => { afterEach(() => { diff --git a/lib/msal-common/test/client/SilentFlowClient.spec.ts b/lib/msal-common/test/client/SilentFlowClient.spec.ts index 05f34baa49..8368d0da15 100644 --- a/lib/msal-common/test/client/SilentFlowClient.spec.ts +++ b/lib/msal-common/test/client/SilentFlowClient.spec.ts @@ -11,7 +11,6 @@ import { TEST_DATA_CLIENT_INFO, ID_TOKEN_CLAIMS, TEST_URIS, - TEST_TOKENS, } from "../test_kit/StringConstants"; import { BaseClient } from "../../src/client/BaseClient"; import { @@ -66,51 +65,41 @@ testAccountEntity.username = ID_TOKEN_CLAIMS.preferred_username; testAccountEntity.name = ID_TOKEN_CLAIMS.name; testAccountEntity.authorityType = "MSSTS"; -const testIdToken: IdTokenEntity = new IdTokenEntity(); -testIdToken.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testIdToken.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testIdToken.environment = testAccountEntity.environment; -testIdToken.realm = ID_TOKEN_CLAIMS.tid; -testIdToken.secret = AUTHENTICATION_RESULT.body.id_token; -testIdToken.credentialType = CredentialType.ID_TOKEN; - -const testAccessTokenEntity: AccessTokenEntity = new AccessTokenEntity(); -testAccessTokenEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testAccessTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testAccessTokenEntity.environment = testAccountEntity.environment; -testAccessTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testAccessTokenEntity.secret = AUTHENTICATION_RESULT.body.access_token; -testAccessTokenEntity.target = - TEST_CONFIG.DEFAULT_SCOPES.join(" ") + - " " + - TEST_CONFIG.DEFAULT_GRAPH_SCOPE.join(" "); -testAccessTokenEntity.credentialType = CredentialType.ACCESS_TOKEN; -testAccessTokenEntity.cachedAt = `${TimeUtils.nowSeconds()}`; -testAccessTokenEntity.tokenType = AuthenticationScheme.BEARER; - -const testAccessTokenWithAuthSchemeEntity: AccessTokenEntity = - new AccessTokenEntity(); -testAccessTokenWithAuthSchemeEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testAccessTokenWithAuthSchemeEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testAccessTokenWithAuthSchemeEntity.environment = testAccountEntity.environment; -testAccessTokenWithAuthSchemeEntity.realm = ID_TOKEN_CLAIMS.tid; -testAccessTokenWithAuthSchemeEntity.secret = TEST_TOKENS.POP_TOKEN; -testAccessTokenWithAuthSchemeEntity.target = - TEST_CONFIG.DEFAULT_SCOPES.join(" ") + - " " + - TEST_CONFIG.DEFAULT_GRAPH_SCOPE.join(" "); -testAccessTokenWithAuthSchemeEntity.credentialType = - CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; -testAccessTokenWithAuthSchemeEntity.cachedAt = `${TimeUtils.nowSeconds()}`; -testAccessTokenWithAuthSchemeEntity.tokenType = AuthenticationScheme.POP; - -const testRefreshTokenEntity: RefreshTokenEntity = new RefreshTokenEntity(); -testRefreshTokenEntity.homeAccountId = `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`; -testRefreshTokenEntity.clientId = TEST_CONFIG.MSAL_CLIENT_ID; -testRefreshTokenEntity.environment = testAccountEntity.environment; -testRefreshTokenEntity.realm = ID_TOKEN_CLAIMS.tid; -testRefreshTokenEntity.secret = AUTHENTICATION_RESULT.body.refresh_token; -testRefreshTokenEntity.credentialType = CredentialType.REFRESH_TOKEN; +const testIdToken: IdTokenEntity = { + homeAccountId: `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: AUTHENTICATION_RESULT.body.id_token, + credentialType: CredentialType.ID_TOKEN, +}; + +const testAccessTokenEntity: AccessTokenEntity = { + homeAccountId: `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: AUTHENTICATION_RESULT.body.access_token, + target: + TEST_CONFIG.DEFAULT_SCOPES.join(" ") + + " " + + TEST_CONFIG.DEFAULT_GRAPH_SCOPE.join(" "), + credentialType: CredentialType.ACCESS_TOKEN, + cachedAt: `${TimeUtils.nowSeconds()}`, + expiresOn: ( + TimeUtils.nowSeconds() + AUTHENTICATION_RESULT.body.expires_in + ).toString(), + tokenType: AuthenticationScheme.BEARER, +}; + +const testRefreshTokenEntity: RefreshTokenEntity = { + homeAccountId: `${TEST_DATA_CLIENT_INFO.TEST_UID}.${TEST_DATA_CLIENT_INFO.TEST_UTID}`, + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + environment: testAccountEntity.environment, + realm: ID_TOKEN_CLAIMS.tid, + secret: AUTHENTICATION_RESULT.body.refresh_token, + credentialType: CredentialType.REFRESH_TOKEN, +}; describe("SilentFlowClient unit tests", () => { const testAccount: AccountInfo = { diff --git a/lib/msal-node/src/cache/NodeStorage.ts b/lib/msal-node/src/cache/NodeStorage.ts index 074918f35e..5878ab4762 100644 --- a/lib/msal-node/src/cache/NodeStorage.ts +++ b/lib/msal-node/src/cache/NodeStorage.ts @@ -19,6 +19,7 @@ import { AuthorityMetadataEntity, ValidCredentialType, StaticAuthorityOptions, + CacheHelpers, } from "@azure/msal-common"; import { Deserializer } from "./serializer/Deserializer.js"; @@ -78,22 +79,20 @@ export class NodeStorage extends CacheManager { }; for (const key in cache) { - if (cache[key as string] instanceof AccountEntity) { - inMemoryCache.accounts[key] = cache[key] as AccountEntity; - } else if (cache[key] instanceof IdTokenEntity) { - inMemoryCache.idTokens[key] = cache[key] as IdTokenEntity; - } else if (cache[key] instanceof AccessTokenEntity) { - inMemoryCache.accessTokens[key] = cache[ - key - ] as AccessTokenEntity; - } else if (cache[key] instanceof RefreshTokenEntity) { - inMemoryCache.refreshTokens[key] = cache[ - key - ] as RefreshTokenEntity; - } else if (cache[key] instanceof AppMetadataEntity) { - inMemoryCache.appMetadata[key] = cache[ - key - ] as AppMetadataEntity; + const value = cache[key]; + if (typeof value !== "object") { + continue; + } + if (value instanceof AccountEntity) { + inMemoryCache.accounts[key] = value as AccountEntity; + } else if (CacheHelpers.isIdTokenEntity(value)) { + inMemoryCache.idTokens[key] = value as IdTokenEntity; + } else if (CacheHelpers.isAccessTokenEntity(value)) { + inMemoryCache.accessTokens[key] = value as AccessTokenEntity; + } else if (CacheHelpers.isRefreshTokenEntity(value)) { + inMemoryCache.refreshTokens[key] = value as RefreshTokenEntity; + } else if (value instanceof AppMetadataEntity) { + inMemoryCache.appMetadata[key] = value as AppMetadataEntity; } else { continue; } @@ -241,7 +240,7 @@ export class NodeStorage extends CacheManager { */ getIdTokenCredential(idTokenKey: string): IdTokenEntity | null { const idToken = this.getItem(idTokenKey) as IdTokenEntity; - if (IdTokenEntity.isIdTokenEntity(idToken)) { + if (CacheHelpers.isIdTokenEntity(idToken)) { return idToken; } return null; @@ -252,7 +251,7 @@ export class NodeStorage extends CacheManager { * @param idToken - cache value to be set of type IdTokenEntity */ setIdTokenCredential(idToken: IdTokenEntity): void { - const idTokenKey = idToken.generateCredentialKey(); + const idTokenKey = CacheHelpers.generateCredentialKey(idToken); this.setItem(idTokenKey, idToken); } @@ -262,7 +261,7 @@ export class NodeStorage extends CacheManager { */ getAccessTokenCredential(accessTokenKey: string): AccessTokenEntity | null { const accessToken = this.getItem(accessTokenKey) as AccessTokenEntity; - if (AccessTokenEntity.isAccessTokenEntity(accessToken)) { + if (CacheHelpers.isAccessTokenEntity(accessToken)) { return accessToken; } return null; @@ -273,7 +272,7 @@ export class NodeStorage extends CacheManager { * @param accessToken - cache value to be set of type AccessTokenEntity */ setAccessTokenCredential(accessToken: AccessTokenEntity): void { - const accessTokenKey = accessToken.generateCredentialKey(); + const accessTokenKey = CacheHelpers.generateCredentialKey(accessToken); this.setItem(accessTokenKey, accessToken); } @@ -287,7 +286,7 @@ export class NodeStorage extends CacheManager { const refreshToken = this.getItem( refreshTokenKey ) as RefreshTokenEntity; - if (RefreshTokenEntity.isRefreshTokenEntity(refreshToken)) { + if (CacheHelpers.isRefreshTokenEntity(refreshToken)) { return refreshToken as RefreshTokenEntity; } return null; @@ -298,7 +297,8 @@ export class NodeStorage extends CacheManager { * @param refreshToken - cache value to be set of type RefreshTokenEntity */ setRefreshTokenCredential(refreshToken: RefreshTokenEntity): void { - const refreshTokenKey = refreshToken.generateCredentialKey(); + const refreshTokenKey = + CacheHelpers.generateCredentialKey(refreshToken); this.setItem(refreshTokenKey, refreshToken); } @@ -516,7 +516,7 @@ export class NodeStorage extends CacheManager { currentCacheKey: string, credential: ValidCredentialType ): string { - const updatedCacheKey = credential.generateCredentialKey(); + const updatedCacheKey = CacheHelpers.generateCredentialKey(credential); if (currentCacheKey !== updatedCacheKey) { const cacheItem = this.getItem(currentCacheKey); diff --git a/lib/msal-node/src/cache/serializer/Deserializer.ts b/lib/msal-node/src/cache/serializer/Deserializer.ts index 5b86b08b9b..023c25f47e 100644 --- a/lib/msal-node/src/cache/serializer/Deserializer.ts +++ b/lib/msal-node/src/cache/serializer/Deserializer.ts @@ -15,6 +15,8 @@ import { RefreshTokenEntity, AppMetadataEntity, CacheManager, + CredentialType, + AuthenticationScheme, } from "@azure/msal-common"; import { JsonCache, @@ -82,16 +84,15 @@ export class Deserializer { if (idTokens) { Object.keys(idTokens).map(function (key) { const serializedIdT = idTokens[key]; - const mappedIdT = { + const idToken: IdTokenEntity = { homeAccountId: serializedIdT.home_account_id, environment: serializedIdT.environment, - credentialType: serializedIdT.credential_type, + credentialType: + serializedIdT.credential_type as CredentialType, clientId: serializedIdT.client_id, secret: serializedIdT.secret, realm: serializedIdT.realm, }; - const idToken: IdTokenEntity = new IdTokenEntity(); - CacheManager.toObject(idToken, mappedIdT); idObjects[key] = idToken; }); } @@ -109,10 +110,11 @@ export class Deserializer { if (accessTokens) { Object.keys(accessTokens).map(function (key) { const serializedAT = accessTokens[key]; - const mappedAT = { + const accessToken: AccessTokenEntity = { homeAccountId: serializedAT.home_account_id, environment: serializedAT.environment, - credentialType: serializedAT.credential_type, + credentialType: + serializedAT.credential_type as CredentialType, clientId: serializedAT.client_id, secret: serializedAT.secret, realm: serializedAT.realm, @@ -122,13 +124,11 @@ export class Deserializer { extendedExpiresOn: serializedAT.extended_expires_on, refreshOn: serializedAT.refresh_on, keyId: serializedAT.key_id, - tokenType: serializedAT.token_type, + tokenType: serializedAT.token_type as AuthenticationScheme, requestedClaims: serializedAT.requestedClaims, requestedClaimsHash: serializedAT.requestedClaimsHash, userAssertionHash: serializedAT.userAssertionHash, }; - const accessToken: AccessTokenEntity = new AccessTokenEntity(); - CacheManager.toObject(accessToken, mappedAT); atObjects[key] = accessToken; }); } @@ -147,19 +147,17 @@ export class Deserializer { if (refreshTokens) { Object.keys(refreshTokens).map(function (key) { const serializedRT = refreshTokens[key]; - const mappedRT = { + const refreshToken: RefreshTokenEntity = { homeAccountId: serializedRT.home_account_id, environment: serializedRT.environment, - credentialType: serializedRT.credential_type, + credentialType: + serializedRT.credential_type as CredentialType, clientId: serializedRT.client_id, secret: serializedRT.secret, familyId: serializedRT.family_id, target: serializedRT.target, realm: serializedRT.realm, }; - const refreshToken: RefreshTokenEntity = - new RefreshTokenEntity(); - CacheManager.toObject(refreshToken, mappedRT); rtObjects[key] = refreshToken; }); } diff --git a/lib/msal-node/test/cache/Storage.spec.ts b/lib/msal-node/test/cache/Storage.spec.ts index db870363ed..d7b21e63f9 100644 --- a/lib/msal-node/test/cache/Storage.spec.ts +++ b/lib/msal-node/test/cache/Storage.spec.ts @@ -3,8 +3,8 @@ import { Logger, AccountEntity, CacheManager, - AccessTokenEntity, AuthorityMetadataEntity, + AccessTokenEntity, IdTokenEntity, RefreshTokenEntity, } from "@azure/msal-common"; @@ -182,25 +182,19 @@ describe("Storage tests for msal-node: ", () => { const accessTokenKey = "uid1.utid1-login.windows.net-accesstoken-mock_client_id-samplerealm-scoperead scopewrite--"; - const newMockAT = { - "uid1.utid1-login.windows.net-accesstoken-mock_client_id-samplerealm-scoperead scopewrite--": - { - homeAccountId: "uid1.utid1", - environment: "login.windows.net", - credentialType: "AccessToken", - clientId: "mock_client_id", - secret: "an access token", - realm: "samplerealm", - target: "scoperead scopewrite", - cachedAt: "1000", - expiresOn: "4600", - extendedExpiresOn: "4600", - }, + const accessToken: AccessTokenEntity = { + homeAccountId: "uid1.utid1", + environment: "login.windows.net", + credentialType: "AccessToken", + clientId: "mock_client_id", + secret: "an access token", + realm: "samplerealm", + target: "scoperead scopewrite", + cachedAt: "1000", + expiresOn: "4600", + extendedExpiresOn: "4600", }; - let accessToken = new AccessTokenEntity(); - accessToken = CacheManager.toObject(accessToken, newMockAT); - const cache = { "uid1.utid1-login.windows.net-accesstoken-mock_client_id-samplerealm-scoperead scopewrite--": accessToken, @@ -221,7 +215,7 @@ describe("Storage tests for msal-node: ", () => { "uid1.utid1-login.windows.net-accesstoken-mock_client_id-samplerealm-scoperead scopewrite--"; const invalidAccessTokenKey = "uid1.utid1-login.windows.net-accesstoken_invalid-mock_client_id-samplerealm-scoperead scopewrite"; - const newMockATData = { + const accessToken: AccessTokenEntity = { homeAccountId: "uid1.utid1", environment: "login.windows.net", credentialType: "AccessToken", @@ -234,9 +228,6 @@ describe("Storage tests for msal-node: ", () => { extendedExpiresOn: "4600", }; - let accessToken = new AccessTokenEntity(); - accessToken = CacheManager.toObject(accessToken, newMockATData); - nodeStorage.setAccessTokenCredential(accessToken); const fetchedAccessToken = nodeStorage.getAccessTokenCredential(accessTokenKey); @@ -259,7 +250,7 @@ describe("Storage tests for msal-node: ", () => { "uid1.utid1-login.windows.net-idtoken-mock_client_id-samplerealm---"; const invalidIdTokenKey = "uid1.utid1-login.windows.net-idtoken_invalid-mock_client_id-samplerealm-"; - const newMockEntityData = { + const idToken: IdTokenEntity = { homeAccountId: "uid1.utid1", environment: "login.windows.net", credentialType: "IdToken", @@ -268,12 +259,6 @@ describe("Storage tests for msal-node: ", () => { realm: "samplerealm", }; - // -\----- - const idToken = CacheManager.toObject( - new IdTokenEntity(), - newMockEntityData - ); - nodeStorage.setIdTokenCredential(idToken); const fetchedIdToken = nodeStorage.getIdTokenCredential(idTokenKey); @@ -295,7 +280,7 @@ describe("Storage tests for msal-node: ", () => { "uid1.utid1-login.windows.net-refreshtoken-mock_client_id-samplerealm---"; const invalidRefreshTokenKey = "uid1.utid1-login.windows.net-refreshtoken_invalid-mock_client_id-samplerealm-"; - const newMockEntityData = { + const refreshToken: RefreshTokenEntity = { homeAccountId: "uid1.utid1", environment: "login.windows.net", credentialType: "RefreshToken", @@ -304,12 +289,6 @@ describe("Storage tests for msal-node: ", () => { realm: "samplerealm", }; - // -\----- - const refreshToken = CacheManager.toObject( - new RefreshTokenEntity(), - newMockEntityData - ); - nodeStorage.setRefreshTokenCredential(refreshToken); const fetchedRefreshToken = diff --git a/lib/msal-node/test/cache/cacheConstants.ts b/lib/msal-node/test/cache/cacheConstants.ts index a8c76fc1ac..3c5827efe2 100644 --- a/lib/msal-node/test/cache/cacheConstants.ts +++ b/lib/msal-node/test/cache/cacheConstants.ts @@ -4,13 +4,14 @@ import { RefreshTokenEntity, AccountEntity, AppMetadataEntity, + CacheHelpers, } from "@azure/msal-common"; export const MOCK_PARTITION_KEY = "mock_partition_key"; export const MOCK_CACHE_STRING = "mock_cache_string"; // mock tokens -export const mockAccessTokenEntity_1 = { +export const mockAccessTokenEntity_1: AccessTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "AccessToken", @@ -24,7 +25,7 @@ export const mockAccessTokenEntity_1 = { userAssertionHash: "mock_hash_string", }; -export const mockAccessTokenEntity_2 = { +export const mockAccessTokenEntity_2: AccessTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "AccessToken", @@ -37,7 +38,7 @@ export const mockAccessTokenEntity_2 = { extendedExpiresOn: "4600", }; -export const mockIdTokenEntity = { +export const mockIdTokenEntity: IdTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "IdToken", @@ -46,7 +47,7 @@ export const mockIdTokenEntity = { realm: "microsoft", }; -export const mockRefreshTokenEntity = { +export const mockRefreshTokenEntity: RefreshTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "RefreshToken", @@ -54,7 +55,7 @@ export const mockRefreshTokenEntity = { secret: "a refresh token", }; -export const mockRefreshTokenEntityWithFamilyId = { +export const mockRefreshTokenEntityWithFamilyId: RefreshTokenEntity = { homeAccountId: "uid.utid", environment: "login.microsoftonline.com", credentialType: "RefreshToken", @@ -82,38 +83,23 @@ export const mockAppMetaDataEntity = { // generate mockCache export class mockCache { static createMockATOne(): AccessTokenEntity { - const at = new AccessTokenEntity(); - Object.assign(at, mockAccessTokenEntity_1); - - return at; + return mockAccessTokenEntity_1; } static createMockATTwo(): AccessTokenEntity { - const at = new AccessTokenEntity(); - Object.assign(at, mockAccessTokenEntity_2); - - return at; + return mockAccessTokenEntity_2; } static createMockIdT(): IdTokenEntity { - const idt = new IdTokenEntity(); - Object.assign(idt, mockIdTokenEntity); - - return idt; + return mockIdTokenEntity; } static createMockRT(): RefreshTokenEntity { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntity); - - return rt; + return mockRefreshTokenEntity; } static createMockRTWithFamilyId(): RefreshTokenEntity { - const rt = new RefreshTokenEntity(); - Object.assign(rt, mockRefreshTokenEntityWithFamilyId); - - return rt; + return mockRefreshTokenEntityWithFamilyId; } static createMockAcc(): AccountEntity { @@ -133,15 +119,17 @@ export class mockCache { export const MockCache = { atOne: mockCache.createMockATOne(), - atOneKey: mockCache.createMockATOne().generateCredentialKey(), + atOneKey: CacheHelpers.generateCredentialKey(mockCache.createMockATOne()), atTwo: mockCache.createMockATTwo(), - atTwoKey: mockCache.createMockATTwo().generateCredentialKey(), + atTwoKey: CacheHelpers.generateCredentialKey(mockCache.createMockATTwo()), idT: mockCache.createMockIdT(), - idTKey: mockCache.createMockIdT().generateCredentialKey(), + idTKey: CacheHelpers.generateCredentialKey(mockCache.createMockIdT()), rt: mockCache.createMockRT(), - rtKey: mockCache.createMockRT().generateCredentialKey(), + rtKey: CacheHelpers.generateCredentialKey(mockCache.createMockRT()), rtF: mockCache.createMockRTWithFamilyId(), - rtFKey: mockCache.createMockRTWithFamilyId().generateCredentialKey(), + rtFKey: CacheHelpers.generateCredentialKey( + mockCache.createMockRTWithFamilyId() + ), acc: mockCache.createMockAcc(), accKey: mockCache.createMockAcc().generateAccountKey(), amdt: mockCache.createMockAmdt(), diff --git a/lib/msal-node/test/client/ClientCredentialClient.spec.ts b/lib/msal-node/test/client/ClientCredentialClient.spec.ts index ce3a52bab5..f662d9033e 100644 --- a/lib/msal-node/test/client/ClientCredentialClient.spec.ts +++ b/lib/msal-node/test/client/ClientCredentialClient.spec.ts @@ -15,6 +15,7 @@ import { TimeUtils, createClientAuthError, ClientAuthErrorCodes, + CacheHelpers, } from "@azure/msal-common"; import { ClientCredentialClient, UsernamePasswordClient } from "../../src"; import { @@ -645,7 +646,7 @@ describe("ClientCredentialClient unit tests", () => { const client = new ClientCredentialClient(config); const expectedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "", "login.microsoftonline.com", "an_access_token", @@ -654,7 +655,7 @@ describe("ClientCredentialClient unit tests", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, undefined, AuthenticationScheme.BEARER ); @@ -708,7 +709,7 @@ describe("ClientCredentialClient unit tests", () => { }; const expectedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "", "login.microsoftonline.com", "an_access_token", @@ -717,7 +718,7 @@ describe("ClientCredentialClient unit tests", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), TimeUtils.nowSeconds() + 4600, TimeUtils.nowSeconds() + 4600, - mockCrypto, + mockCrypto.base64Decode, TimeUtils.nowSeconds() - 4600, // expired refreshOn value AuthenticationScheme.BEARER ); @@ -872,7 +873,7 @@ describe("ClientCredentialClient unit tests", () => { // mock access token const mockedAtEntity: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "", "login.microsoftonline.com", "an_access_token", @@ -881,14 +882,14 @@ describe("ClientCredentialClient unit tests", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, undefined, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN ); const mockedAtEntity2: AccessTokenEntity = - AccessTokenEntity.createAccessTokenEntity( + CacheHelpers.createAccessTokenEntity( "", "login.microsoftonline.com", "an_access_token", @@ -897,7 +898,7 @@ describe("ClientCredentialClient unit tests", () => { TEST_CONFIG.DEFAULT_GRAPH_SCOPE.toString(), 4600, 4600, - mockCrypto, + mockCrypto.base64Decode, undefined, AuthenticationScheme.BEARER, TEST_TOKENS.ACCESS_TOKEN diff --git a/lib/msal-node/test/client/ClientTestUtils.ts b/lib/msal-node/test/client/ClientTestUtils.ts index ef0784d8da..e3618e0289 100644 --- a/lib/msal-node/test/client/ClientTestUtils.ts +++ b/lib/msal-node/test/client/ClientTestUtils.ts @@ -28,6 +28,7 @@ import { TokenKeys, createClientAuthError, ClientAuthErrorCodes, + CacheHelpers, } from "@azure/msal-common"; import { AUTHENTICATION_RESULT, @@ -94,7 +95,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as IdTokenEntity) || null; } setIdTokenCredential(value: IdTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -109,7 +110,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as AccessTokenEntity) || null; } setAccessTokenCredential(value: AccessTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -124,7 +125,7 @@ export class MockStorageClass extends CacheManager { return (this.store[key] as RefreshTokenEntity) || null; } setRefreshTokenCredential(value: RefreshTokenEntity): void { - const key = value.generateCredentialKey(); + const key = CacheHelpers.generateCredentialKey(value); this.store[key] = value; const tokenKeys = this.getTokenKeys(); @@ -188,7 +189,7 @@ export class MockStorageClass extends CacheManager { currentCacheKey: string, credential: ValidCredentialType ): string { - const updatedCacheKey = credential.generateCredentialKey(); + const updatedCacheKey = CacheHelpers.generateCredentialKey(credential); if (currentCacheKey !== updatedCacheKey) { const cacheItem = this.store[currentCacheKey]; diff --git a/lib/msal-node/test/client/OnBehalfOfClient.spec.ts b/lib/msal-node/test/client/OnBehalfOfClient.spec.ts index b36a1e7ee6..a5247e6390 100644 --- a/lib/msal-node/test/client/OnBehalfOfClient.spec.ts +++ b/lib/msal-node/test/client/OnBehalfOfClient.spec.ts @@ -43,28 +43,30 @@ testAccountEntity.username = ID_TOKEN_CLAIMS.preferred_username; testAccountEntity.name = ID_TOKEN_CLAIMS.name; testAccountEntity.authorityType = "MSSTS"; -const testAccessTokenEntity: AccessTokenEntity = new AccessTokenEntity(); -testAccessTokenEntity.homeAccountId = "home_account_id"; -testAccessTokenEntity.clientId = "client_id"; -testAccessTokenEntity.environment = "env"; -testAccessTokenEntity.realm = "this_is_tid"; -testAccessTokenEntity.secret = "access_token"; -testAccessTokenEntity.target = - TEST_CONFIG.DEFAULT_SCOPES.join(" ") + - " " + - TEST_CONFIG.DEFAULT_GRAPH_SCOPE.join(" "); -testAccessTokenEntity.credentialType = CredentialType.ACCESS_TOKEN; -testAccessTokenEntity.cachedAt = `${TimeUtils.nowSeconds()}`; -testAccessTokenEntity.tokenType = AuthenticationScheme.BEARER; -testAccessTokenEntity.userAssertionHash = "user_assertion_hash"; - -const testIdToken: IdTokenEntity = new IdTokenEntity(); -testIdToken.homeAccountId = "home_account_id"; -testIdToken.clientId = "client_id_for_id_token"; -testIdToken.environment = "env_id_token"; -testIdToken.realm = "this_is_tid_id_token"; -testIdToken.secret = TEST_TOKENS.IDTOKEN_V2; -testIdToken.credentialType = CredentialType.ID_TOKEN; +let testAccessTokenEntity: AccessTokenEntity = { + homeAccountId: "home_account_id", + clientId: "client_id", + environment: "env", + realm: "this_is_tid", + secret: "access_token", + target: + TEST_CONFIG.DEFAULT_SCOPES.join(" ") + + " " + + TEST_CONFIG.DEFAULT_GRAPH_SCOPE.join(" "), + credentialType: CredentialType.ACCESS_TOKEN, + cachedAt: `${TimeUtils.nowSeconds()}`, + expiresOn: `${TimeUtils.nowSeconds() + 3600}`, + tokenType: AuthenticationScheme.BEARER, + userAssertionHash: "user_assertion_hash", +}; +const testIdToken: IdTokenEntity = { + homeAccountId: "home_account_id", + clientId: "client_id_for_id_token", + environment: "env_id_token", + realm: "this_is_tid_id_token", + secret: TEST_TOKENS.IDTOKEN_V2, + credentialType: CredentialType.ID_TOKEN, +}; describe("OnBehalfOf unit tests", () => { let config: ClientConfiguration; diff --git a/lib/msal-node/test/client/PublicClientApplication.spec.ts b/lib/msal-node/test/client/PublicClientApplication.spec.ts index 7282bf43e5..1765b0c304 100644 --- a/lib/msal-node/test/client/PublicClientApplication.spec.ts +++ b/lib/msal-node/test/client/PublicClientApplication.spec.ts @@ -22,7 +22,7 @@ import { InteractionRequiredAuthError, AccountEntity, AuthToken, - IdTokenEntity, + CacheHelpers, } from "@azure/msal-common"; import { Configuration, @@ -746,7 +746,7 @@ describe("PublicClientApplication", () => { // @ts-ignore authApp.storage.setAccount(accountEntity); - const idTokenEntity = IdTokenEntity.createIdTokenEntity( + const idTokenEntity = CacheHelpers.createIdTokenEntity( mockAccountInfo.homeAccountId, mockAccountInfo.environment, mockAuthenticationResult.idToken, @@ -835,7 +835,7 @@ describe("PublicClientApplication", () => { // @ts-ignore authApp.storage.setAccount(accountEntity); - const idTokenEntity = IdTokenEntity.createIdTokenEntity( + const idTokenEntity = CacheHelpers.createIdTokenEntity( mockAccountInfo.homeAccountId, mockAccountInfo.environment, mockAuthenticationResult.idToken,