Skip to content

Commit

Permalink
Merge branch 'dev' into preflightBrowserEnvironmentCheck-setinteracti…
Browse files Browse the repository at this point in the history
…oninprogress
  • Loading branch information
hectormmg authored Jun 13, 2022
2 parents adb9326 + e2b46fb commit 7509e54
Show file tree
Hide file tree
Showing 47 changed files with 13,151 additions and 17,130 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add strict assertion checks for OBO clients (#4691)",
"packageName": "@azure/msal-browser",
"email": "bmahal@microsoft.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Return correct fromCache value when tokens are acquired from native broker #4880",
"packageName": "@azure/msal-browser",
"email": "thomas.norling@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Fix ClientAssertion configuration typing between common and node #4846",
"packageName": "@azure/msal-common",
"email": "hemoral@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "Add strict assertion checks for OBO (#4691)",
"packageName": "@azure/msal-common",
"email": "bmahal@microsoft.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add strict assertion checks for OBO clients (#4691)",
"packageName": "@azure/msal-node",
"email": "bmahal@microsoft.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Fix ClientAssertion configuration typing between common and node #4846",
"packageName": "@azure/msal-node",
"email": "hemoral@microsoft.com",
"dependentChangeType": "patch"
}
29 changes: 28 additions & 1 deletion lib/msal-browser/src/broker/nativeBroker/NativeResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,36 @@ export type NativeResponse = {
client_info: string;
expires_in: number;
id_token: string;
properties: object;
properties: NativeResponseProperties;
scopes: string;
state: string;
shr?: string;
extendedLifetimeToken?: boolean;
};

/**
* Properties returned under "properties" of the NativeResponse
*/
export type NativeResponseProperties = {
MATS?: string;
};

/**
* The native token broker can optionally include additional information about operations it performs. If that data is returned, MSAL.js will include the following properties in the telemetry it collects.
*/
export type MATS = {
is_cached?: number;
broker_version?: string;
account_join_on_start?: string;
account_join_on_end?: string;
device_join?: string;
prompt_behavior?: string;
api_error_code?: number;
ui_visible?: boolean;
silent_code?: number;
silent_bi_sub_code?: number;
silent_message?: string;
silent_status?: number;
http_status?: number
http_event_count?: number;
};
4 changes: 2 additions & 2 deletions lib/msal-browser/src/cache/TokenCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ export class TokenCache implements ITokenCache {
const idTokenEntity = IdTokenEntity.createIdTokenEntity(homeAccountId, environment, idToken, this.config.auth.clientId, tenantId);
const idAuthToken = new AuthToken(idToken, this.cryptoObj);
const accountEntity = options.clientInfo ?
AccountEntity.createAccount(options.clientInfo, homeAccountId, idAuthToken, undefined, undefined, undefined, undefined, environment) :
AccountEntity.createGenericAccount(homeAccountId, idAuthToken, undefined, undefined, undefined, undefined, environment);
AccountEntity.createAccount(options.clientInfo, homeAccountId, idAuthToken, undefined, undefined, undefined, environment) :
AccountEntity.createGenericAccount(homeAccountId, idAuthToken, undefined, undefined, undefined, environment);

if (this.isBrowserEnvironment) {
this.logger.verbose("TokenCache - loading id token");
Expand Down
45 changes: 40 additions & 5 deletions lib/msal-browser/src/interaction_client/NativeInteractionClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { PopupRequest } from "../request/PopupRequest";
import { SilentRequest } from "../request/SilentRequest";
import { SsoSilentRequest } from "../request/SsoSilentRequest";
import { NativeMessageHandler } from "../broker/nativeBroker/NativeMessageHandler";
import { NativeExtensionMethod, ApiId, TemporaryCacheKeys } from "../utils/BrowserConstants";
import { NativeExtensionMethod, ApiId, TemporaryCacheKeys, NativeConstants } from "../utils/BrowserConstants";
import { NativeExtensionRequestBody, NativeTokenRequest } from "../broker/nativeBroker/NativeRequest";
import { NativeResponse } from "../broker/nativeBroker/NativeResponse";
import { MATS, NativeResponse } from "../broker/nativeBroker/NativeResponse";
import { NativeAuthError } from "../error/NativeAuthError";
import { RedirectRequest } from "../request/RedirectRequest";
import { NavigationOptions } from "../navigation/NavigationOptions";
Expand Down Expand Up @@ -173,7 +173,7 @@ export class NativeInteractionClient extends BaseInteractionClient {

// Save account in browser storage
const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenObj);
const accountEntity = AccountEntity.createAccount(response.client_info, homeAccountIdentifier, idTokenObj, undefined, undefined, undefined, undefined, authorityPreferredCache, response.account.id);
const accountEntity = AccountEntity.createAccount(response.client_info, homeAccountIdentifier, idTokenObj, undefined, undefined, undefined, authorityPreferredCache, response.account.id);
this.browserStorage.setAccount(accountEntity);

// If scopes not returned in server response, use request scopes
Expand Down Expand Up @@ -225,6 +225,8 @@ export class NativeInteractionClient extends BaseInteractionClient {
}
}

const mats = this.getMATSFromResponse(response);

const result: AuthenticationResult = {
authority: authority.canonicalAuthority,
uniqueId: uid,
Expand All @@ -234,7 +236,7 @@ export class NativeInteractionClient extends BaseInteractionClient {
idToken: response.id_token,
idTokenClaims: idTokenObj.claims,
accessToken: responseAccessToken,
fromCache: false,
fromCache: mats ? this.isResponseFromCache(mats) : false,
expiresOn: new Date(Number(reqTimestamp + response.expires_in) * 1000),
tokenType: responseTokenType,
correlationId: this.correlationId,
Expand Down Expand Up @@ -269,6 +271,37 @@ export class NativeInteractionClient extends BaseInteractionClient {
}
}

/**
* Gets MATS telemetry from native response
* @param response
* @returns
*/
private getMATSFromResponse(response: NativeResponse): MATS|null {
if (response.properties.MATS) {
try {
return JSON.parse(response.properties.MATS);
} catch (e) {
this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
}
}

return null;
}

/**
* Returns whether or not response came from native cache
* @param response
* @returns
*/
private isResponseFromCache(mats: MATS): boolean {
if (typeof mats.is_cached === "undefined") {
this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
return false;
}

return !!mats.is_cached;
}

/**
* Translates developer provided request object into NativeRequest object
* @param request
Expand Down Expand Up @@ -308,9 +341,11 @@ export class NativeInteractionClient extends BaseInteractionClient {
windowTitleSubstring: document.title,
extraParameters: {
...request.extraQueryParameters,
...request.tokenQueryParameters
...request.tokenQueryParameters,
telemetry: NativeConstants.MATS_TELEMETRY
},
extendedExpiryToken: false // Make this configurable?

};

if (request.authenticationScheme === AuthenticationScheme.POP) {
Expand Down
3 changes: 2 additions & 1 deletion lib/msal-browser/src/utils/BrowserConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export const BrowserConstants = {

export const NativeConstants = {
CHANNEL_ID: "53ee284d-920a-4b59-9d30-a60315b26836",
PREFERRED_EXTENSION_ID: "ppnbnpeolgkicgegkbkbjmhlideopiji"
PREFERRED_EXTENSION_ID: "ppnbnpeolgkicgegkbkbjmhlideopiji",
MATS_TELEMETRY: "MATS"
};

export enum NativeExtensionMethod {
Expand Down
12 changes: 6 additions & 6 deletions lib/msal-browser/test/cache/BrowserCacheManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import sinon from "sinon";
import { BrowserAuthErrorMessage } from "../../src/error/BrowserAuthError";
import { TEST_CONFIG, TEST_TOKENS, TEST_DATA_CLIENT_INFO, RANDOM_TEST_GUID, TEST_URIS, TEST_STATE_VALUES, DEFAULT_OPENID_CONFIG_RESPONSE } from "../utils/StringConstants";
import { CacheOptions } from "../../src/config/Configuration";
import { Constants, PersistentCacheKeys, CommonAuthorizationCodeRequest as AuthorizationCodeRequest, ProtocolUtils, Logger, LogLevel, AuthenticationScheme, AuthorityMetadataEntity, AccountEntity, Authority, StubbedNetworkModule, IdToken, IdTokenEntity, AccessTokenEntity, RefreshTokenEntity, AppMetadataEntity, ServerTelemetryEntity, ThrottlingEntity, CredentialType, ProtocolMode, AccountInfo } from "@azure/msal-common";
import { Constants, PersistentCacheKeys, CommonAuthorizationCodeRequest as AuthorizationCodeRequest, ProtocolUtils, Logger, LogLevel, AuthenticationScheme, AuthorityMetadataEntity, AccountEntity, Authority, StubbedNetworkModule, IdToken, IdTokenEntity, AccessTokenEntity, RefreshTokenEntity, AppMetadataEntity, ServerTelemetryEntity, ThrottlingEntity, CredentialType, ProtocolMode, AccountInfo, ClientAuthError, AuthError } from "@azure/msal-common";
import { BrowserCacheLocation, InteractionType, TemporaryCacheKeys } from "../../src/utils/BrowserConstants";
import { CryptoOps } from "../../src/crypto/CryptoOps";
import { DatabaseStorage } from "../../src/cache/DatabaseStorage";
Expand Down Expand Up @@ -271,7 +271,7 @@ describe("BrowserCacheManager tests", () => {
);

it("getIdTokenCredential returns IdTokenEntity", () => {
const testIdToken = IdTokenEntity.createIdTokenEntity("homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, "client-id", "tenantId", "oboAssertion");
const testIdToken = IdTokenEntity.createIdTokenEntity("homeAccountId", "environment", TEST_TOKENS.IDTOKEN_V2, "client-id", "tenantId");

browserLocalStorage.setIdTokenCredential(testIdToken);
browserSessionStorage.setIdTokenCredential(testIdToken);
Expand Down Expand Up @@ -1306,8 +1306,8 @@ describe("BrowserCacheManager tests", () => {
try {
browserStorage.getAccountInfoByHints(accountEntity3.username);
} catch (e) {
expect(e.errorCode).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.code);
expect(e.errorMessage).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.desc);
expect((e as AuthError).errorCode).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.code);
expect((e as AuthError).errorMessage).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.desc);
done();
}
});
Expand Down Expand Up @@ -1341,8 +1341,8 @@ describe("BrowserCacheManager tests", () => {
try {
browserStorage.getAccountInfoByHints(undefined, accountEntity3.idTokenClaims!.sid);
} catch (e) {
expect(e.errorCode).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.code);
expect(e.errorMessage).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.desc);
expect((e as AuthError).errorCode).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.code);
expect((e as AuthError).errorMessage).toEqual(ClientAuthErrorMessage.multipleMatchingAccounts.desc);
done();
}
});
Expand Down
30 changes: 17 additions & 13 deletions lib/msal-browser/test/cache/TokenCache.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

import sinon from "sinon";
import { Logger, LogLevel,IdTokenEntity, AccessTokenEntity, ScopeSet, ExternalTokenResponse, AccountEntity, AuthToken } from "@azure/msal-common";
import { TokenCache, LoadTokenOptions } from "./../../src/cache/TokenCache";
import { TokenCache, LoadTokenOptions } from "../../src/cache/TokenCache";
import { CryptoOps } from "../../src/crypto/CryptoOps";
import { BrowserCacheManager } from "../../src/cache/BrowserCacheManager";
import { BrowserConfiguration, buildConfiguration, CacheOptions } from "../../src/config/Configuration";
import { BrowserCacheLocation } from "../../src/utils/BrowserConstants";
import { TEST_CONFIG, TEST_DATA_CLIENT_INFO, TEST_TOKENS, TEST_TOKEN_LIFETIMES, TEST_URIS } from "../utils/StringConstants";
import { BrowserAuthErrorMessage, SilentRequest } from "../../src";


describe("TokenCache tests", () => {

let configuration: BrowserConfiguration;
Expand All @@ -27,7 +31,7 @@ describe("TokenCache tests", () => {
cacheLocation: BrowserCacheLocation.SessionStorage,
storeAuthStateInCookie: false,
secureCookies: false
};
};
logger = new Logger({
loggerCallback: (level: LogLevel, message: string, containsPii: boolean): void => {},
piiLoggingEnabled: true
Expand Down Expand Up @@ -60,7 +64,7 @@ describe("TokenCache tests", () => {
testEnvironment = 'login.microsoftonline.com';

testClientInfo = `${TEST_DATA_CLIENT_INFO.TEST_UID_ENCODED}.${TEST_DATA_CLIENT_INFO.TEST_UTID_ENCODED}`;

testIdToken = TEST_TOKENS.IDTOKEN_V2;
idTokenEntity = IdTokenEntity.createIdTokenEntity(TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, testEnvironment, TEST_TOKENS.IDTOKEN_V2, configuration.auth.clientId, TEST_CONFIG.TENANT)
idTokenKey = idTokenEntity.generateCredentialKey();
Expand All @@ -83,14 +87,14 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: TEST_DATA_CLIENT_INFO.TEST_LOCAL_ACCOUNT_ID
localAccountId: TEST_DATA_CLIENT_INFO.TEST_LOCAL_ACCOUNT_ID
}
};
const response: ExternalTokenResponse = {
id_token: testIdToken
};
const options: LoadTokenOptions = {};
tokenCache.loadExternalTokens(request, response, options);
tokenCache.loadExternalTokens(request, response, options);

expect(browserStorage.getIdTokenCredential(idTokenKey)).toEqual(idTokenEntity);
});
Expand Down Expand Up @@ -123,7 +127,7 @@ describe("TokenCache tests", () => {
clientInfo: testClientInfo
};
const testIdAuthToken = new AuthToken(testIdToken, cryptoObj);
const testAccount = AccountEntity.createAccount(testClientInfo, TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, testIdAuthToken, undefined, undefined, undefined, undefined, testEnvironment);
const testAccount = AccountEntity.createAccount(testClientInfo, TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, testIdAuthToken, undefined, undefined, undefined, testEnvironment, undefined);
const testAccountInfo = {
homeAccountId: TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID,
environment: testEnvironment,
Expand Down Expand Up @@ -161,7 +165,7 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: "localAccountId"
localAccountId: "localAccountId"
}
};
const response: ExternalTokenResponse = {};
Expand Down Expand Up @@ -203,7 +207,7 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: "localAccountId"
localAccountId: "localAccountId"
}
};
const response: ExternalTokenResponse = {
Expand All @@ -223,7 +227,7 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: "localAccountId"
localAccountId: "localAccountId"
}
};
const response: ExternalTokenResponse = {
Expand All @@ -244,7 +248,7 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: "localAccountId"
localAccountId: "localAccountId"
}
};
const response: ExternalTokenResponse = {
Expand All @@ -256,7 +260,7 @@ describe("TokenCache tests", () => {
expiresOn: TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP,
extendedExpiresOn: TEST_TOKEN_LIFETIMES.TEST_ACCESS_TOKEN_EXP
};
tokenCache.loadExternalTokens(request, response, options);
tokenCache.loadExternalTokens(request, response, options);

expect(parseInt(accessTokenEntity.expiresOn)).toBeGreaterThan(TEST_TOKEN_LIFETIMES.DEFAULT_EXPIRES_IN);
expect(browserStorage.getAccessTokenCredential(accessTokenKey)).toEqual(accessTokenEntity);
Expand All @@ -271,7 +275,7 @@ describe("TokenCache tests", () => {
environment: testEnvironment,
tenantId: TEST_CONFIG.TENANT,
username: "username",
localAccountId: "localAccountId"
localAccountId: "localAccountId"
}
};
const response: ExternalTokenResponse = {
Expand Down
Loading

0 comments on commit 7509e54

Please sign in to comment.