diff --git a/change/@azure-msal-browser-8017ad17-73f7-4627-b31f-e8bc1f0bd541.json b/change/@azure-msal-browser-8017ad17-73f7-4627-b31f-e8bc1f0bd541.json new file mode 100644 index 0000000000..8c888a2a9e --- /dev/null +++ b/change/@azure-msal-browser-8017ad17-73f7-4627-b31f-e8bc1f0bd541.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix bug affecting metadata resolution for tenanted authorities", + "packageName": "@azure/msal-browser", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-msal-common-c8346546-a98e-47fe-83b2-fcb5ceb36845.json b/change/@azure-msal-common-c8346546-a98e-47fe-83b2-fcb5ceb36845.json new file mode 100644 index 0000000000..63b90dc912 --- /dev/null +++ b/change/@azure-msal-common-c8346546-a98e-47fe-83b2-fcb5ceb36845.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix bug affecting metadata resolution for tenanted authorities", + "packageName": "@azure/msal-common", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-msal-node-8042a4bb-8629-4d03-9fc0-9ad9f3ffca48.json b/change/@azure-msal-node-8042a4bb-8629-4d03-9fc0-9ad9f3ffca48.json new file mode 100644 index 0000000000..08cbdb5ed8 --- /dev/null +++ b/change/@azure-msal-node-8042a4bb-8629-4d03-9fc0-9ad9f3ffca48.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix bug affecting metadata resolution for tenanted authorities", + "packageName": "@azure/msal-node", + "email": "thomas.norling@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/lib/msal-browser/src/cache/TokenCache.ts b/lib/msal-browser/src/cache/TokenCache.ts index bb282913e9..fc407423a6 100644 --- a/lib/msal-browser/src/cache/TokenCache.ts +++ b/lib/msal-browser/src/cache/TokenCache.ts @@ -31,6 +31,7 @@ import { } from "../error/BrowserAuthError"; import { AuthenticationResult } from "../response/AuthenticationResult"; import { base64Decode } from "../encode/Base64Decode"; +import * as BrowserCrypto from "../crypto/BrowserCrypto"; export type LoadTokenOptions = { clientInfo?: string; @@ -142,7 +143,8 @@ export class TokenCache implements ITokenCache { this.config.system.networkClient, this.storage, authorityOptions, - this.logger + this.logger, + request.correlationId || BrowserCrypto.createNewGuid() ); // "clientInfo" from options takes precedence over "clientInfo" in response diff --git a/lib/msal-browser/src/interaction_client/BaseInteractionClient.ts b/lib/msal-browser/src/interaction_client/BaseInteractionClient.ts index 7ceaad9dfb..bee98d77ba 100644 --- a/lib/msal-browser/src/interaction_client/BaseInteractionClient.ts +++ b/lib/msal-browser/src/interaction_client/BaseInteractionClient.ts @@ -279,28 +279,16 @@ export abstract class BaseInteractionClient { authorityMetadata: this.config.auth.authorityMetadata, }; - if (requestAuthority) { - this.logger.verbose( - "Creating discovered authority with request authority" - ); - return AuthorityFactory.createDiscoveredInstance( - requestAuthority, - this.config.system.networkClient, - this.browserStorage, - authorityOptions, - this.logger - ); - } - - this.logger.verbose( - "Creating discovered authority with configured authority" - ); + const authority = requestAuthority || this.config.auth.authority; + this.logger.verbose(`Creating discovered authority with ${authority}`); return AuthorityFactory.createDiscoveredInstance( - this.config.auth.authority, + authority, this.config.system.networkClient, this.browserStorage, authorityOptions, - this.logger + this.logger, + this.correlationId, + this.performanceClient ); } } diff --git a/lib/msal-browser/src/interaction_client/StandardInteractionClient.ts b/lib/msal-browser/src/interaction_client/StandardInteractionClient.ts index d7a09c634d..acfec17800 100644 --- a/lib/msal-browser/src/interaction_client/StandardInteractionClient.ts +++ b/lib/msal-browser/src/interaction_client/StandardInteractionClient.ts @@ -331,8 +331,8 @@ export abstract class StandardInteractionClient extends BaseInteractionClient { this.browserStorage, authorityOptions, this.logger, - this.performanceClient, - this.correlationId + this.correlationId, + this.performanceClient ); } diff --git a/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts b/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts index bb4651ad80..8f8cec03c2 100644 --- a/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts +++ b/lib/msal-browser/test/cache/BrowserCacheManager.spec.ts @@ -347,7 +347,8 @@ describe("BrowserCacheManager tests", () => { cloudDiscoveryMetadata: "", knownAuthorities: [], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Pre-populate localstorage with accounts const testAccount = AccountEntity.createAccount( @@ -425,7 +426,8 @@ describe("BrowserCacheManager tests", () => { cloudDiscoveryMetadata: "", knownAuthorities: [], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); sinon .stub(Authority.prototype, "getPreferredCache") @@ -1615,7 +1617,8 @@ describe("BrowserCacheManager tests", () => { cloudDiscoveryMetadata: "", knownAuthorities: [], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); sinon .stub(Authority.prototype, "getPreferredCache") diff --git a/lib/msal-browser/test/interaction_handler/InteractionHandler.spec.ts b/lib/msal-browser/test/interaction_handler/InteractionHandler.spec.ts index e9db85304b..8b23ec7faa 100644 --- a/lib/msal-browser/test/interaction_handler/InteractionHandler.spec.ts +++ b/lib/msal-browser/test/interaction_handler/InteractionHandler.spec.ts @@ -11,7 +11,6 @@ import { LogLevel, LoggerOptions, AccountInfo, - AuthorityFactory, CommonAuthorizationCodeRequest, AuthenticationResult, AuthorizationCodeClient, @@ -82,7 +81,7 @@ class TestInteractionHandler extends InteractionHandler { const testAuthCodeRequest: CommonAuthorizationCodeRequest = { authenticationScheme: AuthenticationScheme.BEARER, - authority: "", + authority: TEST_CONFIG.validAuthority, redirectUri: TEST_URIS.TEST_REDIR_URI, scopes: ["scope1", "scope2"], code: "", @@ -171,11 +170,10 @@ let authConfig: ClientConfiguration; describe("InteractionHandler.ts Unit Tests", () => { let authCodeModule: AuthorizationCodeClient; - let browserRequestLogger: Logger; let browserStorage: BrowserCacheManager; const cryptoOpts = new CryptoOps(testBrowserRequestLogger); - beforeEach(() => { + beforeEach(async () => { const appConfig: Configuration = { auth: { clientId: TEST_CONFIG.MSAL_CLIENT_ID, @@ -193,13 +191,21 @@ describe("InteractionHandler.ts Unit Tests", () => { piiLoggingEnabled: true, }; const logger: Logger = new Logger(loggerOptions); - authorityInstance = AuthorityFactory.createInstance( + browserStorage = new BrowserCacheManager( + TEST_CONFIG.MSAL_CLIENT_ID, + configObj.cache, + cryptoOpts, + logger + ); + authorityInstance = new Authority( configObj.auth.authority, networkInterface, browserStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); + await authorityInstance.resolveEndpointsAsync(); authConfig = { authOptions: { ...configObj.auth, @@ -232,13 +238,6 @@ describe("InteractionHandler.ts Unit Tests", () => { loggerOptions: loggerOptions, }; authCodeModule = new AuthorizationCodeClient(authConfig); - browserRequestLogger = new Logger(authConfig.loggerOptions!); - browserStorage = new BrowserCacheManager( - TEST_CONFIG.MSAL_CLIENT_ID, - configObj.cache, - cryptoOpts, - logger - ); }); afterEach(() => { @@ -272,7 +271,6 @@ describe("InteractionHandler.ts Unit Tests", () => { code: "authcode", nonce: idTokenClaims.nonce, state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, - cloud_instance_host_name: "contoso.com", }; const testAccount: AccountInfo = { homeAccountId: TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, @@ -319,29 +317,6 @@ describe("InteractionHandler.ts Unit Tests", () => { TemporaryCacheKeys.CCS_CREDENTIAL, CcsCredentialType.UPN ); - - sinon.stub(Authority.prototype, "isAlias").returns(false); - const authorityOptions: AuthorityOptions = { - protocolMode: ProtocolMode.AAD, - knownAuthorities: ["www.contoso.com"], - cloudDiscoveryMetadata: "", - authorityMetadata: "", - }; - const authority = new Authority( - "https://www.contoso.com/common/", - networkInterface, - browserStorage, - authorityOptions, - browserRequestLogger - ); - sinon - .stub(AuthorityFactory, "createDiscoveredInstance") - .resolves(authority); - sinon.stub(Authority.prototype, "discoveryComplete").returns(true); - const updateAuthoritySpy = sinon.spy( - AuthorizationCodeClient.prototype, - "updateAuthority" - ); const acquireTokenSpy = sinon .stub(AuthorizationCodeClient.prototype, "acquireToken") .resolves(testTokenResponse); @@ -355,7 +330,7 @@ describe("InteractionHandler.ts Unit Tests", () => { await interactionHandler.handleCodeResponseFromServer( testCodeResponse, { - authority: "https://www.contoso.com/common/", + authority: TEST_CONFIG.validAuthority, scopes: ["User.Read"], correlationId: TEST_CONFIG.CORRELATION_ID, redirectUri: "/", @@ -365,12 +340,6 @@ describe("InteractionHandler.ts Unit Tests", () => { } ); - expect( - updateAuthoritySpy.calledWith( - "contoso.com", - TEST_CONFIG.CORRELATION_ID - ) - ).toBe(true); expect(tokenResponse).toEqual(testTokenResponse); expect( acquireTokenSpy.calledWith( @@ -400,7 +369,7 @@ describe("InteractionHandler.ts Unit Tests", () => { code: "authcode", nonce: idTokenClaims.nonce, state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, - cloud_instance_host_name: "contoso.com", + cloud_instance_host_name: "login.windows.net", }; const testAccount: AccountInfo = { homeAccountId: TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, @@ -444,24 +413,6 @@ describe("InteractionHandler.ts Unit Tests", () => { "handleFragmentResponse" ) .returns(testCodeResponse); - sinon.stub(Authority.prototype, "isAlias").returns(false); - const authorityOptions: AuthorityOptions = { - protocolMode: ProtocolMode.AAD, - knownAuthorities: ["www.contoso.com"], - cloudDiscoveryMetadata: "", - authorityMetadata: "", - }; - const authority = new Authority( - "https://www.contoso.com/common/", - networkInterface, - browserStorage, - authorityOptions, - browserRequestLogger - ); - sinon - .stub(AuthorityFactory, "createDiscoveredInstance") - .resolves(authority); - sinon.stub(Authority.prototype, "discoveryComplete").returns(true); const updateAuthoritySpy = sinon.spy( AuthorizationCodeClient.prototype, "updateAuthority" @@ -480,7 +431,7 @@ describe("InteractionHandler.ts Unit Tests", () => { state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, }, { - authority: "https://www.contoso.com/common/", + authority: TEST_CONFIG.validAuthority, scopes: ["User.Read"], correlationId: TEST_CONFIG.CORRELATION_ID, redirectUri: "/", @@ -491,7 +442,7 @@ describe("InteractionHandler.ts Unit Tests", () => { ); expect( updateAuthoritySpy.calledWith( - "contoso.com", + testCodeResponse.cloud_instance_host_name, TEST_CONFIG.CORRELATION_ID ) ).toBe(true); @@ -521,7 +472,6 @@ describe("InteractionHandler.ts Unit Tests", () => { code: "authcode", nonce: idTokenClaims.nonce, state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, - cloud_instance_host_name: "contoso.com", }; const testAccount: AccountInfo = { homeAccountId: TEST_DATA_CLIENT_INFO.TEST_HOME_ACCOUNT_ID, @@ -574,28 +524,6 @@ describe("InteractionHandler.ts Unit Tests", () => { "handleFragmentResponse" ) .returns(testCodeResponse); - sinon.stub(Authority.prototype, "isAlias").returns(false); - const authorityOptions: AuthorityOptions = { - protocolMode: ProtocolMode.AAD, - knownAuthorities: ["www.contoso.com"], - cloudDiscoveryMetadata: "", - authorityMetadata: "", - }; - const authority = new Authority( - "https://www.contoso.com/common/", - networkInterface, - browserStorage, - authorityOptions, - browserRequestLogger - ); - sinon - .stub(AuthorityFactory, "createDiscoveredInstance") - .resolves(authority); - sinon.stub(Authority.prototype, "discoveryComplete").returns(true); - const updateAuthoritySpy = sinon.spy( - AuthorizationCodeClient.prototype, - "updateAuthority" - ); const acquireTokenSpy = sinon .stub(AuthorizationCodeClient.prototype, "acquireToken") .resolves(testTokenResponse); @@ -610,7 +538,7 @@ describe("InteractionHandler.ts Unit Tests", () => { state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, }, { - authority: "https://www.contoso.com/common/", + authority: TEST_CONFIG.validAuthority, scopes: ["User.Read"], correlationId: TEST_CONFIG.CORRELATION_ID, redirectUri: "/", @@ -619,12 +547,6 @@ describe("InteractionHandler.ts Unit Tests", () => { state: TEST_STATE_VALUES.TEST_STATE_REDIRECT, } ); - expect( - updateAuthoritySpy.calledWith( - "contoso.com", - TEST_CONFIG.CORRELATION_ID - ) - ).toBe(true); expect(tokenResponse).toEqual(testTokenResponse); expect( acquireTokenSpy.calledWith( diff --git a/lib/msal-browser/test/interaction_handler/RedirectHandler.spec.ts b/lib/msal-browser/test/interaction_handler/RedirectHandler.spec.ts index 4de21e72b0..a1784e1be9 100644 --- a/lib/msal-browser/test/interaction_handler/RedirectHandler.spec.ts +++ b/lib/msal-browser/test/interaction_handler/RedirectHandler.spec.ts @@ -112,12 +112,13 @@ describe("RedirectHandler.ts Unit Tests", () => { piiLoggingEnabled: true, }; const logger: Logger = new Logger(loggerOptions); - authorityInstance = AuthorityFactory.createInstance( + authorityInstance = new Authority( configObj.auth.authority, networkInterface, browserStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); browserCrypto = new CryptoOps(logger); browserStorage = new BrowserCacheManager( diff --git a/lib/msal-common/src/authority/Authority.ts b/lib/msal-common/src/authority/Authority.ts index 1bc69e5119..fd16bbbec2 100644 --- a/lib/msal-common/src/authority/Authority.ts +++ b/lib/msal-common/src/authority/Authority.ts @@ -86,7 +86,7 @@ export class Authority { // Performance client protected performanceClient: IPerformanceClient | undefined; // Correlation Id - protected correlationId: string | undefined; + protected correlationId: string; // Reserved tenant domain names that will not be replaced with tenant id private static reservedTenantDomains: Set = new Set([ "{tenant}", @@ -102,8 +102,8 @@ export class Authority { cacheManager: ICacheManager, authorityOptions: AuthorityOptions, logger: Logger, - performanceClient?: IPerformanceClient, - correlationId?: string + correlationId: string, + performanceClient?: IPerformanceClient ) { this.canonicalAuthority = authority; this._canonicalAuthority.validateAsUri(); @@ -422,6 +422,13 @@ export class Authority { this.updateCachedMetadata(metadataEntity, cloudDiscoverySource, { source: endpointSource, }); + this.performanceClient?.addFields( + { + cloudDiscoverySource: cloudDiscoverySource, + authorityEndpointSource: endpointSource, + }, + this.correlationId + ); } /** @@ -734,8 +741,8 @@ export class Authority { * Get OAuth endpoints for common authorities. */ private getEndpointMetadataFromHardcodedValues(): OpenIdConfigResponse | null { - if (this.canonicalAuthority in EndpointMetadata) { - return EndpointMetadata[this.canonicalAuthority]; + if (this.hostnameAndPort in EndpointMetadata) { + return EndpointMetadata[this.hostnameAndPort]; } return null; diff --git a/lib/msal-common/src/authority/AuthorityFactory.ts b/lib/msal-common/src/authority/AuthorityFactory.ts index 17046ea6d2..1cced7fd8e 100644 --- a/lib/msal-common/src/authority/AuthorityFactory.ts +++ b/lib/msal-common/src/authority/AuthorityFactory.ts @@ -4,10 +4,6 @@ */ import { Authority, formatAuthorityUri } from "./Authority"; -import { - createClientConfigurationError, - ClientConfigurationErrorCodes, -} from "../error/ClientConfigurationError"; import { INetworkModule } from "../network/INetworkModule"; import { createClientAuthError, @@ -20,99 +16,59 @@ import { IPerformanceClient } from "../telemetry/performance/IPerformanceClient" import { PerformanceEvents } from "../telemetry/performance/PerformanceEvent"; import { invokeAsync } from "../utils/FunctionWrappers"; -/** @internal */ -export class AuthorityFactory { - /** - * Create an authority object of the correct type based on the url - * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs) - * - * Also performs endpoint discovery. - * - * @param authorityUri - * @param networkClient - * @param protocolMode - */ - static async createDiscoveredInstance( - authorityUri: string, - networkClient: INetworkModule, - cacheManager: ICacheManager, - authorityOptions: AuthorityOptions, - logger: Logger, - performanceClient?: IPerformanceClient, - correlationId?: string - ): Promise { - performanceClient?.addQueueMeasurement( - PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance, - correlationId - ); - const authorityUriFinal = Authority.transformCIAMAuthority( - formatAuthorityUri(authorityUri) - ); - - // Initialize authority and perform discovery endpoint check. - const acquireTokenAuthority: Authority = - AuthorityFactory.createInstance( - authorityUriFinal, - networkClient, - cacheManager, - authorityOptions, - logger, - performanceClient, - correlationId - ); - - try { - await invokeAsync( - acquireTokenAuthority.resolveEndpointsAsync.bind( - acquireTokenAuthority - ), - PerformanceEvents.AuthorityResolveEndpointsAsync, - logger, - performanceClient, - correlationId - )(); - return acquireTokenAuthority; - } catch (e) { - throw createClientAuthError( - ClientAuthErrorCodes.endpointResolutionError - ); - } - } +/** + * Create an authority object of the correct type based on the url + * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs) + * + * Also performs endpoint discovery. + * + * @param authorityUri + * @param networkClient + * @param protocolMode + * @internal + */ +export async function createDiscoveredInstance( + authorityUri: string, + networkClient: INetworkModule, + cacheManager: ICacheManager, + authorityOptions: AuthorityOptions, + logger: Logger, + correlationId: string, + performanceClient?: IPerformanceClient +): Promise { + performanceClient?.addQueueMeasurement( + PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance, + correlationId + ); + const authorityUriFinal = Authority.transformCIAMAuthority( + formatAuthorityUri(authorityUri) + ); - /** - * Create an authority object of the correct type based on the url - * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs) - * - * Does not perform endpoint discovery. - * - * @param authorityUrl - * @param networkInterface - * @param protocolMode - */ - static createInstance( - authorityUrl: string, - networkInterface: INetworkModule, - cacheManager: ICacheManager, - authorityOptions: AuthorityOptions, - logger: Logger, - performanceClient?: IPerformanceClient, - correlationId?: string - ): Authority { - // Throw error if authority url is empty - if (!authorityUrl) { - throw createClientConfigurationError( - ClientConfigurationErrorCodes.urlEmptyError - ); - } + // Initialize authority and perform discovery endpoint check. + const acquireTokenAuthority: Authority = new Authority( + authorityUriFinal, + networkClient, + cacheManager, + authorityOptions, + logger, + correlationId, + performanceClient + ); - return new Authority( - authorityUrl, - networkInterface, - cacheManager, - authorityOptions, + try { + await invokeAsync( + acquireTokenAuthority.resolveEndpointsAsync.bind( + acquireTokenAuthority + ), + PerformanceEvents.AuthorityResolveEndpointsAsync, logger, performanceClient, correlationId + )(); + return acquireTokenAuthority; + } catch (e) { + throw createClientAuthError( + ClientAuthErrorCodes.endpointResolutionError ); } } diff --git a/lib/msal-common/src/authority/AuthorityMetadata.ts b/lib/msal-common/src/authority/AuthorityMetadata.ts index c6e2f44491..ca4d5c6682 100644 --- a/lib/msal-common/src/authority/AuthorityMetadata.ts +++ b/lib/msal-common/src/authority/AuthorityMetadata.ts @@ -8,556 +8,53 @@ import { UrlString } from "../url/UrlString"; import { AuthorityMetadataSource } from "../utils/Constants"; import { StaticAuthorityOptions } from "./AuthorityOptions"; import { CloudDiscoveryMetadata } from "./CloudDiscoveryMetadata"; +import { CloudInstanceDiscoveryResponse } from "./CloudInstanceDiscoveryResponse"; +import { OpenIdConfigResponse } from "./OpenIdConfigResponse"; -export const rawMetdataJSON = { +type RawMetadata = { + endpointMetadata: { [key: string]: OpenIdConfigResponse }; + instanceDiscoveryMetadata: CloudInstanceDiscoveryResponse; +}; + +export const rawMetdataJSON: RawMetadata = { endpointMetadata: { - "https://login.microsoftonline.com/common/": { - token_endpoint: - "https://login.microsoftonline.com/common/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.microsoftonline.com/common/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.microsoftonline.com/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.microsoftonline.com/common/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.com/common/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.com", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pas.windows.net", - }, - "https://login.chinacloudapi.cn/common/": { - token_endpoint: - "https://login.chinacloudapi.cn/common/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.chinacloudapi.cn/common/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.partner.microsoftonline.cn/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: - "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", - authorization_endpoint: - "https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.chinacloudapi.cn/common/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.chinacloudapi.cn/common/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: "https://login.chinacloudapi.cn/common/kerberos", - tenant_region_scope: null, - cloud_instance_name: "partner.microsoftonline.cn", - cloud_graph_host_name: "graph.chinacloudapi.cn", - msgraph_host: "microsoftgraph.chinacloudapi.cn", - rbac_url: "https://pas.chinacloudapi.cn", - }, - "https://login.microsoftonline.us/common/": { - token_endpoint: - "https://login.microsoftonline.us/common/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.microsoftonline.us/common/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.microsoftonline.us/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.microsoftonline.us/common/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.us/common/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.microsoftonline.us/common/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.us/common/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.us", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pasff.usgovcloudapi.net", - }, - "https://login.microsoftonline.com/consumers/": { - token_endpoint: - "https://login.microsoftonline.com/consumers/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.microsoftonline.com/consumers/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.microsoftonline.com/consumers/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.com/consumers/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.com", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pas.windows.net", - }, - "https://login.chinacloudapi.cn/consumers/": { - token_endpoint: - "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.chinacloudapi.cn/consumers/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.partner.microsoftonline.cn/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: - "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", - authorization_endpoint: - "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.chinacloudapi.cn/consumers/kerberos", - tenant_region_scope: null, - cloud_instance_name: "partner.microsoftonline.cn", - cloud_graph_host_name: "graph.chinacloudapi.cn", - msgraph_host: "microsoftgraph.chinacloudapi.cn", - rbac_url: "https://pas.chinacloudapi.cn", - }, - "https://login.microsoftonline.us/consumers/": { - token_endpoint: - "https://login.microsoftonline.us/consumers/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], - jwks_uri: - "https://login.microsoftonline.us/consumers/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], - issuer: "https://login.microsoftonline.us/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", - authorization_endpoint: - "https://login.microsoftonline.us/consumers/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.us/consumers/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, - end_session_endpoint: - "https://login.microsoftonline.us/consumers/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.us/consumers/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.us", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pasff.usgovcloudapi.net", - }, - "https://login.microsoftonline.com/organizations/": { + "login.microsoftonline.com": { token_endpoint: - "https://login.microsoftonline.com/organizations/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], + "https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token", jwks_uri: - "https://login.microsoftonline.com/organizations/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], + "https://login.microsoftonline.com/{tenantid}/discovery/v2.0/keys", issuer: "https://login.microsoftonline.com/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", authorization_endpoint: - "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, + "https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/authorize", end_session_endpoint: - "https://login.microsoftonline.com/organizations/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.com/organizations/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.com", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pas.windows.net", + "https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/logout", }, - "https://login.chinacloudapi.cn/organizations/": { + "login.chinacloudapi.cn": { token_endpoint: - "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], + "https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/token", jwks_uri: - "https://login.chinacloudapi.cn/organizations/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], + "https://login.chinacloudapi.cn/{tenantid}/discovery/v2.0/keys", issuer: "https://login.partner.microsoftonline.cn/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: - "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", authorization_endpoint: - "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, + "https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/authorize", end_session_endpoint: - "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.chinacloudapi.cn/organizations/kerberos", - tenant_region_scope: null, - cloud_instance_name: "partner.microsoftonline.cn", - cloud_graph_host_name: "graph.chinacloudapi.cn", - msgraph_host: "microsoftgraph.chinacloudapi.cn", - rbac_url: "https://pas.chinacloudapi.cn", + "https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/logout", }, - "https://login.microsoftonline.us/organizations/": { + "login.microsoftonline.us": { token_endpoint: - "https://login.microsoftonline.us/organizations/oauth2/v2.0/token", - token_endpoint_auth_methods_supported: [ - "client_secret_post", - "private_key_jwt", - "client_secret_basic", - ], + "https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/token", jwks_uri: - "https://login.microsoftonline.us/organizations/discovery/v2.0/keys", - response_modes_supported: ["query", "fragment", "form_post"], - subject_types_supported: ["pairwise"], - id_token_signing_alg_values_supported: ["RS256"], - response_types_supported: [ - "code", - "id_token", - "code id_token", - "id_token token", - ], - scopes_supported: ["openid", "profile", "email", "offline_access"], + "https://login.microsoftonline.us/{tenantid}/discovery/v2.0/keys", issuer: "https://login.microsoftonline.us/{tenantid}/v2.0", - request_uri_parameter_supported: false, - userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo", authorization_endpoint: - "https://login.microsoftonline.us/organizations/oauth2/v2.0/authorize", - device_authorization_endpoint: - "https://login.microsoftonline.us/organizations/oauth2/v2.0/devicecode", - http_logout_supported: true, - frontchannel_logout_supported: true, + "https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/authorize", end_session_endpoint: - "https://login.microsoftonline.us/organizations/oauth2/v2.0/logout", - claims_supported: [ - "sub", - "iss", - "cloud_instance_name", - "cloud_instance_host_name", - "cloud_graph_host_name", - "msgraph_host", - "aud", - "exp", - "iat", - "auth_time", - "acr", - "nonce", - "preferred_username", - "name", - "tid", - "ver", - "at_hash", - "c_hash", - "email", - ], - kerberos_endpoint: - "https://login.microsoftonline.us/organizations/kerberos", - tenant_region_scope: null, - cloud_instance_name: "microsoftonline.us", - cloud_graph_host_name: "graph.windows.net", - msgraph_host: "graph.microsoft.com", - rbac_url: "https://pasff.usgovcloudapi.net", + "https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/logout", }, }, instanceDiscoveryMetadata: { tenant_discovery_endpoint: "https://{canonicalAuthority}/v2.0/.well-known/openid-configuration", - "api-version": "1.1", metadata: [ { preferred_network: "login.microsoftonline.com", diff --git a/lib/msal-common/src/client/BaseClient.ts b/lib/msal-common/src/client/BaseClient.ts index f87fc57199..00bcbf171a 100644 --- a/lib/msal-common/src/client/BaseClient.ts +++ b/lib/msal-common/src/client/BaseClient.ts @@ -24,7 +24,7 @@ import { buildClientInfoFromHomeAccountId } from "../account/ClientInfo"; import { IPerformanceClient } from "../telemetry/performance/IPerformanceClient"; import { RequestParameterBuilder } from "../request/RequestParameterBuilder"; import { BaseAuthRequest } from "../request/BaseAuthRequest"; -import { AuthorityFactory } from "../authority/AuthorityFactory"; +import { createDiscoveredInstance } from "../authority/AuthorityFactory"; import { PerformanceEvents } from "../telemetry/performance/PerformanceEvent"; /** @@ -191,16 +191,15 @@ export abstract class BaseClient { correlationId ); const cloudInstanceAuthorityUri = `https://${cloudInstanceHostname}/${this.authority.tenant}/`; - const cloudInstanceAuthority = - await AuthorityFactory.createDiscoveredInstance( - cloudInstanceAuthorityUri, - this.networkClient, - this.cacheManager, - this.authority.options, - this.logger, - this.performanceClient, - correlationId - ); + const cloudInstanceAuthority = await createDiscoveredInstance( + cloudInstanceAuthorityUri, + this.networkClient, + this.cacheManager, + this.authority.options, + this.logger, + correlationId, + this.performanceClient + ); this.authority = cloudInstanceAuthority; } diff --git a/lib/msal-common/src/index.ts b/lib/msal-common/src/index.ts index 59c99b5ca1..04d9560749 100644 --- a/lib/msal-common/src/index.ts +++ b/lib/msal-common/src/index.ts @@ -59,7 +59,7 @@ export { AzureCloudInstance, StaticAuthorityOptions, } from "./authority/AuthorityOptions"; -export { AuthorityFactory } from "./authority/AuthorityFactory"; +export * as AuthorityFactory from "./authority/AuthorityFactory"; export { AuthorityType } from "./authority/AuthorityType"; export { ProtocolMode } from "./authority/ProtocolMode"; export { OIDCOptions } from "./authority/OIDCOptions"; diff --git a/lib/msal-common/test/authority/Authority.spec.ts b/lib/msal-common/test/authority/Authority.spec.ts index ab58915cd6..c7c786c577 100644 --- a/lib/msal-common/test/authority/Authority.spec.ts +++ b/lib/msal-common/test/authority/Authority.spec.ts @@ -117,7 +117,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authority.canonicalAuthority).toBe( `${Constants.DEFAULT_AUTHORITY}` @@ -149,7 +150,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ) ).toThrowError( ClientConfigurationErrorMessage.authorityUriInsecure.desc @@ -161,7 +163,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ) ).toThrowError(ClientConfigurationErrorMessage.urlParseError.desc); expect( @@ -171,7 +174,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ) ).toThrowError(ClientConfigurationErrorMessage.urlEmptyError.desc); }); @@ -201,7 +205,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); }); @@ -328,7 +333,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(() => authority.authorizationEndpoint).toThrowError( createClientAuthError( @@ -381,7 +387,8 @@ describe("Authority.ts Class Unit Tests", () => { ...authorityOptions, knownAuthorities: ["msidlabb2c.b2clogin.com"], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -393,7 +400,8 @@ describe("Authority.ts Class Unit Tests", () => { ...authorityOptions, knownAuthorities: ["msidlabb2c.b2clogin.com"], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await secondAuthority.resolveEndpointsAsync(); @@ -453,7 +461,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -497,7 +506,8 @@ describe("Authority.ts Class Unit Tests", () => { ...authorityOptions, knownAuthorities: ["msidlabb2c.b2clogin.com"], }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await customAuthority.resolveEndpointsAsync(); @@ -543,7 +553,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await customAuthority.resolveEndpointsAsync(); @@ -622,7 +633,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -677,7 +689,8 @@ describe("Authority.ts Class Unit Tests", () => { environmentRegion: "centralus", }, }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -737,7 +750,8 @@ describe("Authority.ts Class Unit Tests", () => { environmentRegion: "centralus", }, }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -794,7 +808,8 @@ describe("Authority.ts Class Unit Tests", () => { environmentRegion: "centralus", }, }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -849,7 +864,8 @@ describe("Authority.ts Class Unit Tests", () => { environmentRegion: undefined, }, }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -899,7 +915,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); }); @@ -977,7 +994,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, options, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1059,7 +1077,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, options, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); authority.resolveEndpointsAsync().catch((e) => { expect(e).toBeInstanceOf(ClientConfigurationError); @@ -1088,7 +1107,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, options, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1120,7 +1140,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, customAuthorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1163,6 +1184,65 @@ describe("Authority.ts Class Unit Tests", () => { ).not.toHaveBeenCalled(); }); + it("Gets endpoints for tenanted Microsoft authority from hardcoded values", async () => { + const customAuthorityOptions: AuthorityOptions = { + protocolMode: ProtocolMode.AAD, + knownAuthorities: [], + cloudDiscoveryMetadata: "", + authorityMetadata: "", + skipAuthorityMetadataCache: false, + }; + + const tenantId = "fake-tenant-id"; + authority = new Authority( + `https://login.microsoftonline.com/${tenantId}`, + networkInterface, + mockStorage, + customAuthorityOptions, + logger, + TEST_CONFIG.CORRELATION_ID + ); + + await authority.resolveEndpointsAsync(); + + expect(authority.discoveryComplete()).toBe(true); + expect(authority.authorizationEndpoint).toBe( + DEFAULT_OPENID_CONFIG_RESPONSE.body.authorization_endpoint.replace( + "{tenant}", + tenantId + ) + ); + expect(authority.tokenEndpoint).toBe( + DEFAULT_OPENID_CONFIG_RESPONSE.body.token_endpoint.replace( + "{tenant}", + tenantId + ) + ); + expect(authority.deviceCodeEndpoint).toBe( + authority.tokenEndpoint.replace("/token", "/devicecode") + ); + expect(authority.endSessionEndpoint).toBe( + DEFAULT_OPENID_CONFIG_RESPONSE.body.end_session_endpoint.replace( + "{tenant}", + tenantId + ) + ); + expect(authority.selfSignedJwtAudience).toBe( + DEFAULT_OPENID_CONFIG_RESPONSE.body.issuer.replace( + "{tenant}", + tenantId + ) + ); + + expect(getEndpointMetadataFromConfigSpy).toHaveBeenCalled(); + expect( + getEndpointMetadataFromHarcodedValuesSpy + ).toHaveBeenCalled(); + expect( + getEndpointMetadataFromNetworkSpy + ).not.toHaveBeenCalled(); + }); + it("Gets endpoints from hardcoded values with regional information", async () => { const customAuthorityOptions: AuthorityOptions = { protocolMode: ProtocolMode.AAD, @@ -1203,7 +1283,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, customAuthorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1251,7 +1332,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Force hardcoded metadata to return null @@ -1335,7 +1417,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, { ...authorityOptions, skipAuthorityMetadataCache: true }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Force hardcoded metadata to return null @@ -1425,7 +1508,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Force hardcoded metadata to return null @@ -1508,7 +1592,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); getEndpointMetadataFromHarcodedValuesSpy.mockReturnValue(null); @@ -1590,7 +1675,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, { ...authorityOptions, skipAuthorityMetadataCache: true }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); authority.resolveEndpointsAsync().catch((e) => { expect(e).toBeInstanceOf(ClientAuthError); @@ -1621,7 +1707,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); expect( @@ -1688,7 +1775,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1736,7 +1824,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1832,7 +1921,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -1881,7 +1971,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); const hardcodedCloudDiscoveryMetadata = @@ -1951,7 +2042,8 @@ describe("Authority.ts Class Unit Tests", () => { ...authorityOptions, skipAuthorityMetadataCache: true, }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); getCloudDiscoveryMetadataFromHarcodedValuesSpy.mockReturnValue( @@ -2041,7 +2133,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); getCloudDiscoveryMetadataFromHarcodedValuesSpy.mockReturnValue( @@ -2123,7 +2216,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); getCloudDiscoveryMetadataFromHarcodedValuesSpy.mockReturnValue( null @@ -2174,7 +2268,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); getCloudDiscoveryMetadataFromHarcodedValuesSpy.mockReturnValue( @@ -2257,7 +2352,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -2321,7 +2417,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -2374,7 +2471,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); authority.resolveEndpointsAsync().catch((e) => { expect(e).toBeInstanceOf(ClientConfigurationError); @@ -2405,7 +2503,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); authority.resolveEndpointsAsync().catch((e) => { @@ -2444,7 +2543,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); authority.resolveEndpointsAsync().catch((e) => { @@ -2486,7 +2586,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync(); @@ -2506,25 +2607,18 @@ describe("Authority.ts Class Unit Tests", () => { it("ADFS authority uses v1 well-known endpoint", async () => { const authorityUrl = "https://login.microsoftonline.com/adfs/"; - let endpoint = ""; authority = new Authority( authorityUrl, networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); - jest.spyOn( - networkInterface, - "sendGetRequestAsync" - ).mockImplementation((openIdConfigEndpoint) => { - // @ts-ignore - endpoint = openIdConfigEndpoint; - return DEFAULT_OPENID_CONFIG_RESPONSE; - }); await authority.resolveEndpointsAsync(); - expect(endpoint).toBe( + // @ts-ignore + expect(authority.defaultOpenIdConfigurationEndpoint).toBe( `${authorityUrl}.well-known/openid-configuration` ); }); @@ -2537,7 +2631,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, { ...authorityOptions, knownAuthorities: [authorityUrl] }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); jest.spyOn( networkInterface, @@ -2557,25 +2652,18 @@ describe("Authority.ts Class Unit Tests", () => { it("v2 is not added to authority if already provided", async () => { const authorityUrl = "https://login.microsoftonline.com/test-tenant-id/v2.0"; - let endpoint = ""; authority = new Authority( authorityUrl, networkInterface, mockStorage, { ...authorityOptions, knownAuthorities: [authorityUrl] }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); - jest.spyOn( - networkInterface, - "sendGetRequestAsync" - ).mockImplementation((openIdConfigEndpoint) => { - // @ts-ignore - endpoint = openIdConfigEndpoint; - return DEFAULT_OPENID_CONFIG_RESPONSE; - }); await authority.resolveEndpointsAsync(); - expect(endpoint).toBe( + // @ts-ignore + expect(authority.defaultOpenIdConfigurationEndpoint).toBe( `${authorityUrl}/.well-known/openid-configuration` ); }); @@ -2583,50 +2671,36 @@ describe("Authority.ts Class Unit Tests", () => { it("DSTS authority uses v2 well-known endpoint with common authority", async () => { const authorityUrl = "https://login.microsoftonline.com/dstsv2/common/"; - let endpoint = ""; authority = new Authority( authorityUrl, networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); - jest.spyOn( - networkInterface, - "sendGetRequestAsync" - ).mockImplementation((openIdConfigEndpoint) => { - // @ts-ignore - endpoint = openIdConfigEndpoint; - return DEFAULT_OPENID_CONFIG_RESPONSE; - }); await authority.resolveEndpointsAsync(); - expect(endpoint).toBe( + // @ts-ignore + expect(authority.defaultOpenIdConfigurationEndpoint).toBe( `${authorityUrl}v2.0/.well-known/openid-configuration` ); }); it("DSTS authority uses v2 well-known with tenanted authority", async () => { const authorityUrl = `https://login.microsoftonline.com/dstsv2/${TEST_CONFIG.TENANT}/`; - let endpoint = ""; authority = new Authority( authorityUrl, networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); - jest.spyOn( - networkInterface, - "sendGetRequestAsync" - ).mockImplementation((openIdConfigEndpoint) => { - // @ts-ignore - endpoint = openIdConfigEndpoint; - return DEFAULT_OPENID_CONFIG_RESPONSE; - }); await authority.resolveEndpointsAsync(); - expect(endpoint).toBe( + // @ts-ignore + expect(authority.defaultOpenIdConfigurationEndpoint).toBe( `${authorityUrl}v2.0/.well-known/openid-configuration` ); }); @@ -2645,7 +2719,8 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, options, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); jest.spyOn( networkInterface, @@ -2664,7 +2739,6 @@ describe("Authority.ts Class Unit Tests", () => { it("Does append v2 to endpoint when using a known Microsoft authority", async () => { const authorityUrl = "https://login.microsoftonline.com/"; - let endpoint = ""; const options = { protocolMode: ProtocolMode.OIDC, knownAuthorities: [Constants.DEFAULT_AUTHORITY], @@ -2676,19 +2750,13 @@ describe("Authority.ts Class Unit Tests", () => { networkInterface, mockStorage, options, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); - jest.spyOn( - networkInterface, - "sendGetRequestAsync" - ).mockImplementation((openIdConfigEndpoint) => { - // @ts-ignore - endpoint = openIdConfigEndpoint; - return DEFAULT_OPENID_CONFIG_RESPONSE; - }); await authority.resolveEndpointsAsync(); - expect(endpoint).toBe( + // @ts-ignore + expect(authority.defaultOpenIdConfigurationEndpoint).toBe( `${authorityUrl}v2.0/.well-known/openid-configuration` ); }); diff --git a/lib/msal-common/test/authority/AuthorityFactory.spec.ts b/lib/msal-common/test/authority/AuthorityFactory.spec.ts index bb361bbb71..c6d9edc159 100644 --- a/lib/msal-common/test/authority/AuthorityFactory.spec.ts +++ b/lib/msal-common/test/authority/AuthorityFactory.spec.ts @@ -1,11 +1,10 @@ -import { AuthorityFactory } from "../../src/authority/AuthorityFactory"; +import * as AuthorityFactory from "../../src/authority/AuthorityFactory"; import { INetworkModule, NetworkRequestOptions, } from "../../src/network/INetworkModule"; import { TEST_CONFIG } from "../test_kit/StringConstants"; import { Constants } from "../../src/utils/Constants"; -import { ClientConfigurationErrorMessage } from "../../src/error/ClientConfigurationError"; import { Authority } from "../../src/authority/Authority"; import { AuthorityType } from "../../src/authority/AuthorityType"; import { MockCache } from "../cache/MockCache"; @@ -61,121 +60,6 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { jest.clearAllMocks(); }); - it("AuthorityFactory returns null if given url is null or empty", () => { - expect(() => - AuthorityFactory.createInstance( - "", - networkInterface, - mockStorage, - authorityOptions, - logger - ) - ).toThrowError(ClientConfigurationErrorMessage.urlEmptyError.desc); - - expect(() => - AuthorityFactory.createInstance( - // @ts-ignore - null, - networkInterface, - mockStorage, - authorityOptions, - logger - ) - ).toThrowError(ClientConfigurationErrorMessage.urlEmptyError.desc); - }); - - it("Throws error for malformed url strings", () => { - expect(() => - AuthorityFactory.createInstance( - "http://login.microsoftonline.com/common", - networkInterface, - mockStorage, - authorityOptions, - logger - ) - ).toThrowError( - ClientConfigurationErrorMessage.authorityUriInsecure.desc - ); - expect(() => - AuthorityFactory.createInstance( - "This is not a URI", - networkInterface, - mockStorage, - authorityOptions, - logger - ) - ).toThrowError(ClientConfigurationErrorMessage.urlParseError.desc); - expect(() => - AuthorityFactory.createInstance( - "", - networkInterface, - mockStorage, - authorityOptions, - logger - ) - ).toThrowError(ClientConfigurationErrorMessage.urlEmptyError.desc); - }); - - it("createInstance returns Default instance if AAD Authority", () => { - const authorityInstance = AuthorityFactory.createInstance( - Constants.DEFAULT_AUTHORITY, - networkInterface, - mockStorage, - authorityOptions, - logger - ); - expect(authorityInstance.authorityType).toBe(AuthorityType.Default); - expect(authorityInstance instanceof Authority); - }); - - it("createInstance returns Default instance if B2C Authority", () => { - const authorityInstance = AuthorityFactory.createInstance( - TEST_CONFIG.b2cValidAuthority, - networkInterface, - mockStorage, - authorityOptions, - logger - ); - expect(authorityInstance.authorityType).toBe(AuthorityType.Default); - expect(authorityInstance instanceof Authority); - }); - - it("createInstance return ADFS instance if /adfs in path", () => { - const authorityInstanceAAD = AuthorityFactory.createInstance( - TEST_CONFIG.ADFS_VALID_AUTHORITY, - networkInterface, - mockStorage, - authorityOptions, - logger - ); - expect(authorityInstanceAAD.authorityType).toBe(AuthorityType.Adfs); - expect(authorityInstanceAAD instanceof Authority); - - authorityOptions.protocolMode = ProtocolMode.OIDC; - const authorityInstanceOIDC = AuthorityFactory.createInstance( - TEST_CONFIG.ADFS_VALID_AUTHORITY, - networkInterface, - mockStorage, - authorityOptions, - logger - ); - expect(authorityInstanceOIDC.authorityType).toBe(AuthorityType.Adfs); - expect(authorityInstanceOIDC instanceof Authority); - }); - - it("createInstance returns (non v2) OIDC endpoint with ProtocolMode: OIDC", () => { - authorityOptions.protocolMode = ProtocolMode.OIDC; - const authorityInstance = AuthorityFactory.createInstance( - Constants.DEFAULT_AUTHORITY, - networkInterface, - mockStorage, - authorityOptions, - logger - ); - expect(authorityInstance.authorityType).toBe(AuthorityType.Default); - expect(authorityInstance instanceof Authority); - }); - it("createDiscoveredInstance calls resolveEndpointsAsync then returns authority", async () => { const resolveEndpointsStub = jest .spyOn(Authority.prototype, "resolveEndpointsAsync") @@ -186,7 +70,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Default); expect(authorityInstance instanceof Authority); @@ -202,7 +87,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ).catch((e) => { expect(e).toBeInstanceOf(ClientAuthError); expect(e.errorCode).toBe( @@ -223,7 +109,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Ciam); expect(authorityInstance.canonicalAuthority).toBe( @@ -243,7 +130,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Ciam); expect(authorityInstance.canonicalAuthority).toBe( @@ -263,7 +151,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Ciam); expect(authorityInstance.canonicalAuthority).toBe( @@ -283,7 +172,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Ciam); expect(authorityInstance.canonicalAuthority).toBe( @@ -303,7 +193,8 @@ describe("AuthorityFactory.ts Class Unit Tests", () => { networkInterface, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); expect(authorityInstance.authorityType).toBe(AuthorityType.Ciam); expect(authorityInstance.canonicalAuthority).toBe( diff --git a/lib/msal-common/test/cache/entities/AccountEntity.spec.ts b/lib/msal-common/test/cache/entities/AccountEntity.spec.ts index ec87226ad8..e859485783 100644 --- a/lib/msal-common/test/cache/entities/AccountEntity.spec.ts +++ b/lib/msal-common/test/cache/entities/AccountEntity.spec.ts @@ -1,7 +1,6 @@ import { AccountEntity } from "../../../src/cache/entities/AccountEntity"; import { mockAccountEntity, mockIdTokenEntity } from "./cacheConstants"; import * as AuthToken from "../../../src/account/AuthToken"; -import { AuthorityFactory } from "../../../src/authority/AuthorityFactory"; import { CacheAccountType, Constants } from "../../../src/utils/Constants"; import { NetworkRequestOptions, @@ -18,6 +17,7 @@ import { TEST_CRYPTO_VALUES, ID_TOKEN_CLAIMS, GUEST_ID_TOKEN_CLAIMS, + TEST_CONFIG, } from "../../test_kit/StringConstants"; import sinon from "sinon"; import { MockStorageClass, mockCrypto } from "../../client/ClientTestUtils"; @@ -104,12 +104,13 @@ const loggerOptions = { }; const logger = new Logger(loggerOptions); -const authority = AuthorityFactory.createInstance( +const authority = new Authority( Constants.DEFAULT_AUTHORITY, networkInterface, new MockStorageClass("client-id", mockCrypto, logger), authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); describe("AccountEntity.ts Unit Tests", () => { @@ -254,12 +255,13 @@ describe("AccountEntity.ts Unit Tests", () => { }); it("create an Account no preferred_username or emails claim", () => { - const authority = AuthorityFactory.createInstance( + const authority = new Authority( Constants.DEFAULT_AUTHORITY, networkInterface, new MockStorageClass("client-id", mockCrypto, logger), authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Set up stubs @@ -301,7 +303,7 @@ describe("AccountEntity.ts Unit Tests", () => { }); it("creates a generic account", () => { - const authority = AuthorityFactory.createInstance( + const authority = new Authority( Constants.DEFAULT_AUTHORITY, networkInterface, new MockStorageClass("client-id", mockCrypto, logger), @@ -311,7 +313,8 @@ describe("AccountEntity.ts Unit Tests", () => { cloudDiscoveryMetadata: "", authorityMetadata: "", }, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Set up stubs @@ -635,12 +638,13 @@ describe("AccountEntity.ts Unit Tests for ADFS", () => { cloudDiscoveryMetadata: "", authorityMetadata: "", }; - const authority = AuthorityFactory.createInstance( + const authority = new Authority( "https://myadfs.com/adfs", networkInterface, new MockStorageClass("client-id", mockCrypto, logger), authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Set up stubs @@ -688,12 +692,13 @@ describe("AccountEntity.ts Unit Tests for ADFS", () => { cloudDiscoveryMetadata: "", authorityMetadata: "", }; - const authority = AuthorityFactory.createInstance( + const authority = new Authority( "https://myadfs.com/adfs", networkInterface, new MockStorageClass("client-id", mockCrypto, logger), authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); // Set up stubs diff --git a/lib/msal-common/test/client/ClientTestUtils.ts b/lib/msal-common/test/client/ClientTestUtils.ts index ec4d2f2588..aeafc9c8d3 100644 --- a/lib/msal-common/test/client/ClientTestUtils.ts +++ b/lib/msal-common/test/client/ClientTestUtils.ts @@ -13,7 +13,6 @@ import { AccessTokenEntity, RefreshTokenEntity, ProtocolMode, - AuthorityFactory, AuthorityOptions, AuthorityMetadataEntity, ValidCredentialType, @@ -24,6 +23,7 @@ import { createClientAuthError, ClientAuthErrorCodes, CacheHelpers, + Authority, } from "../../src"; import { RANDOM_TEST_GUID, @@ -285,12 +285,13 @@ export class ClientTestUtils { }; const logger = new Logger(loggerOptions); - const authority = AuthorityFactory.createInstance( + const authority = new Authority( TEST_CONFIG.validAuthority, mockHttpClient, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync().catch((error) => { diff --git a/lib/msal-common/test/response/ResponseHandler.spec.ts b/lib/msal-common/test/response/ResponseHandler.spec.ts index cb7f3ec72a..739d42b23e 100644 --- a/lib/msal-common/test/response/ResponseHandler.spec.ts +++ b/lib/msal-common/test/response/ResponseHandler.spec.ts @@ -160,7 +160,8 @@ const testAuthority = new Authority( networkInterface, testCacheManager, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); describe("ResponseHandler.ts", () => { diff --git a/lib/msal-node/src/client/ClientApplication.ts b/lib/msal-node/src/client/ClientApplication.ts index 9cf87ff37d..6015ef446d 100644 --- a/lib/msal-node/src/client/ClientApplication.ts +++ b/lib/msal-node/src/client/ClientApplication.ts @@ -396,7 +396,7 @@ export abstract class ClientApplication { */ protected async buildOauthClientConfiguration( authority: string, - requestCorrelationId?: string, + requestCorrelationId: string, serverTelemetryManager?: ServerTelemetryManager, azureRegionConfiguration?: AzureRegionConfiguration, azureCloudOptions?: AzureCloudOptions @@ -414,8 +414,8 @@ export abstract class ClientApplication { // using null assertion operator as we ensure that all config values have default values in buildConfiguration() const discoveredAuthority = await this.createAuthority( authority, - azureRegionConfiguration, requestCorrelationId, + azureRegionConfiguration, userAzureCloudOptions ); @@ -559,8 +559,8 @@ export abstract class ClientApplication { */ private async createAuthority( authorityString: string, + requestCorrelationId: string, azureRegionConfiguration?: AzureRegionConfiguration, - requestCorrelationId?: string, azureCloudOptions?: AzureCloudOptions ): Promise { this.logger.verbose("createAuthority called", requestCorrelationId); @@ -586,7 +586,8 @@ export abstract class ClientApplication { this.config.system.networkClient, this.storage, authorityOptions, - this.logger + this.logger, + requestCorrelationId ); } diff --git a/lib/msal-node/test/client/ClientTestUtils.ts b/lib/msal-node/test/client/ClientTestUtils.ts index 984a845164..c64aade304 100644 --- a/lib/msal-node/test/client/ClientTestUtils.ts +++ b/lib/msal-node/test/client/ClientTestUtils.ts @@ -19,7 +19,6 @@ import { AccessTokenEntity, RefreshTokenEntity, ProtocolMode, - AuthorityFactory, AuthorityOptions, AuthorityMetadataEntity, ValidCredentialType, @@ -29,6 +28,7 @@ import { createClientAuthError, ClientAuthErrorCodes, CacheHelpers, + Authority, } from "@azure/msal-common"; import { AUTHENTICATION_RESULT, @@ -298,12 +298,13 @@ export class ClientTestUtils { }; const logger = new Logger(loggerOptions); - const authority = AuthorityFactory.createInstance( + const authority = new Authority( TEST_CONFIG.validAuthority, mockHttpClient, mockStorage, authorityOptions, - logger + logger, + TEST_CONFIG.CORRELATION_ID ); await authority.resolveEndpointsAsync().catch(() => { diff --git a/lib/msal-node/test/client/ConfidentialClientApplication.spec.ts b/lib/msal-node/test/client/ConfidentialClientApplication.spec.ts index e953d0a33d..1aa98f8ba7 100644 --- a/lib/msal-node/test/client/ConfidentialClientApplication.spec.ts +++ b/lib/msal-node/test/client/ConfidentialClientApplication.spec.ts @@ -1,5 +1,4 @@ import { - ClientConfiguration, AuthorizationCodeClient, RefreshTokenClient, AuthenticationResult, @@ -20,10 +19,6 @@ import { ClientCredentialClient, RefreshTokenRequest, } from "../../src"; -import { - fakeAuthority, - setupAuthorityFactory_createDiscoveredInstance_mock, -} from "./test-fixtures"; import * as msalNode from "../../src"; import { getMsalCommonAutoMock, MSALCommonModule } from "../utils/MockUtils"; @@ -43,17 +38,6 @@ describe("ConfidentialClientApplication", () => { }, }; - const expectedConfig: ClientConfiguration = { - authOptions: { - clientId: TEST_CONSTANTS.CLIENT_ID, - authority: fakeAuthority, - clientCapabilities: [], - }, - clientCredentials: { - clientSecret: TEST_CONSTANTS.CLIENT_SECRET, - }, - }; - test("exports a class", () => { const authApp = new ConfidentialClientApplication(appConfig); expect(authApp).toBeInstanceOf(ConfidentialClientApplication); @@ -66,10 +50,8 @@ describe("ConfidentialClientApplication", () => { code: TEST_CONSTANTS.AUTHORIZATION_CODE, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); const mockAuthCodeClientInstance = { includeRedirectUri: false, - acquireToken: jest.fn(), }; jest.spyOn(msalCommon, "AuthorizationCodeClient").mockImplementation( @@ -80,9 +62,6 @@ describe("ConfidentialClientApplication", () => { const authApp = new ConfidentialClientApplication(appConfig); await authApp.acquireTokenByCode(request); expect(AuthorizationCodeClient).toHaveBeenCalledTimes(1); - expect(AuthorizationCodeClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByRefreshToken", async () => { @@ -91,8 +70,6 @@ describe("ConfidentialClientApplication", () => { refreshToken: TEST_CONSTANTS.REFRESH_TOKEN, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - const { RefreshTokenClient: mockRefreshTokenClient } = getMsalCommonAutoMock(); @@ -111,9 +88,6 @@ describe("ConfidentialClientApplication", () => { const authApp = new ConfidentialClientApplication(appConfig); await authApp.acquireTokenByRefreshToken(request); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByClientCredential", async () => { @@ -141,7 +115,6 @@ describe("ConfidentialClientApplication", () => { scopes: TEST_CONSTANTS.DEFAULT_GRAPH_SCOPE, skipCache: false, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); const authApp = new ConfidentialClientApplication( configWithExtensibility @@ -158,7 +131,6 @@ describe("ConfidentialClientApplication", () => { skipCache: false, clientAssertion: "testAssertion", }; - setupAuthorityFactory_createDiscoveredInstance_mock(); ClientCredentialClient.prototype.acquireToken = jest.fn( (request: CommonClientCredentialRequest) => { @@ -183,16 +155,11 @@ describe("ConfidentialClientApplication", () => { oboAssertion: TEST_CONSTANTS.ACCESS_TOKEN, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - const onBehalfOfClientSpy = jest.spyOn(msalNode, "OnBehalfOfClient"); const authApp = new ConfidentialClientApplication(appConfig); await authApp.acquireTokenOnBehalfOf(request); expect(onBehalfOfClientSpy).toHaveBeenCalledTimes(1); - expect(onBehalfOfClientSpy).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByUsernamePassword", async () => { @@ -202,8 +169,6 @@ describe("ConfidentialClientApplication", () => { password: TEST_CONSTANTS.PASSWORD, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - const usernamePasswordClientSpy = jest.spyOn( msalNode, "UsernamePasswordClient" @@ -212,9 +177,6 @@ describe("ConfidentialClientApplication", () => { const authApp = new ConfidentialClientApplication(appConfig); await authApp.acquireTokenByUsernamePassword(request); expect(usernamePasswordClientSpy).toHaveBeenCalledTimes(1); - expect(usernamePasswordClientSpy).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test('acquireTokenByClientCredential throws missingTenantIdError if "common", ""organization", or "consumers" was provided as the tenant id', async () => { @@ -243,8 +205,6 @@ describe("ConfidentialClientApplication", () => { skipCache: false, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - const authApp = new ConfidentialClientApplication(appConfig); authApp.SetAppTokenProvider(testProvider); @@ -261,8 +221,6 @@ describe("ConfidentialClientApplication", () => { skipCache: false, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - jest.spyOn(AuthError.prototype, "setCorrelationId"); jest.spyOn( @@ -289,8 +247,6 @@ describe("ConfidentialClientApplication", () => { skipCache: false, }; - setupAuthorityFactory_createDiscoveredInstance_mock(); - jest.spyOn( ClientCredentialClient.prototype, "acquireToken" diff --git a/lib/msal-node/test/client/PublicClientApplication.spec.ts b/lib/msal-node/test/client/PublicClientApplication.spec.ts index db465b3567..b2c7e426b8 100644 --- a/lib/msal-node/test/client/PublicClientApplication.spec.ts +++ b/lib/msal-node/test/client/PublicClientApplication.spec.ts @@ -9,12 +9,10 @@ import { DEFAULT_OPENID_CONFIG_RESPONSE, } from "../utils/TestConstants"; import { - ClientConfiguration, AuthenticationResult, AuthorizationCodeClient, RefreshTokenClient, SilentFlowClient, - ProtocolMode, Logger, LogLevel, AccountInfo, @@ -23,6 +21,8 @@ import { AccountEntity, AuthToken, CacheHelpers, + AuthorityFactory, + ProtocolMode, } from "@azure/msal-common"; import { Configuration, @@ -37,17 +37,11 @@ import { AuthorizationUrlRequest, UsernamePasswordRequest, SilentFlowRequest, - NodeStorage, } from "../../src"; -import { HttpClient } from "../../src/network/HttpClient"; import http from "http"; import * as msalNode from "../../src"; -import { - fakeAuthority, - setupAuthorityFactory_createDiscoveredInstance_mock, - setupServerTelemetryManagerMock, -} from "./test-fixtures"; +import { setupServerTelemetryManagerMock } from "./test-fixtures"; import { getMsalCommonAutoMock, MSALCommonModule } from "../utils/MockUtils"; import { version, name } from "../../package.json"; @@ -56,6 +50,9 @@ import { SignOutRequest } from "../../src/request/SignOutRequest"; import { LoopbackClient } from "../../src/network/LoopbackClient"; import { createClientAuthError } from "@azure/msal-common"; import { ClientAuthErrorCodes } from "@azure/msal-common"; +import { TEST_CONFIG } from "../test_kit/StringConstants"; +import { HttpClient } from "../../src/network/HttpClient"; +import { MockStorageClass } from "./ClientTestUtils"; const msalCommon: MSALCommonModule = jest.requireActual("@azure/msal-common"); @@ -87,17 +84,8 @@ describe("PublicClientApplication", () => { }, }; - const expectedConfig: ClientConfiguration = { - authOptions: { - clientId: TEST_CONSTANTS.CLIENT_ID, - authority: fakeAuthority, - clientCapabilities: [], - }, - }; - beforeEach(() => { mockTelemetryManager; - setupAuthorityFactory_createDiscoveredInstance_mock(); }); afterEach(() => { @@ -129,9 +117,6 @@ describe("PublicClientApplication", () => { const authApp = new PublicClientApplication(appConfig); const result = await authApp.acquireTokenByDeviceCode(request); expect(deviceCodeClientSpy).toHaveBeenCalledTimes(1); - expect(deviceCodeClientSpy).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); expect(result).toEqual(fakeAuthResult); }); @@ -153,9 +138,6 @@ describe("PublicClientApplication", () => { await authApp.acquireTokenByCode(request); expect(AuthorizationCodeClient).toHaveBeenCalledTimes(1); - expect(AuthorizationCodeClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByAuthorizationCode with nonce", async () => { @@ -182,9 +164,6 @@ describe("PublicClientApplication", () => { await authApp.acquireTokenByCode(request, authCodePayLoad); expect(AuthorizationCodeClient).toHaveBeenCalledTimes(1); - expect(AuthorizationCodeClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByAuthorizationCode with state validation", async () => { @@ -212,9 +191,6 @@ describe("PublicClientApplication", () => { await authApp.acquireTokenByCode(request, authCodePayLoad); expect(AuthorizationCodeClient).toHaveBeenCalledTimes(1); - expect(AuthorizationCodeClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenByRefreshToken", async () => { @@ -232,9 +208,6 @@ describe("PublicClientApplication", () => { const authApp = new PublicClientApplication(appConfig); await authApp.acquireTokenByRefreshToken(request); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); describe("acquireTokenSilent tests", () => { @@ -252,9 +225,6 @@ describe("PublicClientApplication", () => { const authApp = new PublicClientApplication(appConfig); await authApp.acquireTokenSilent(request); expect(SilentFlowClient).toHaveBeenCalledTimes(1); - expect(SilentFlowClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireTokenSilent calls into NativeBrokerPlugin and returns result", async () => { @@ -740,7 +710,23 @@ describe("PublicClientApplication", () => { cryptoProvider.base64Decode ), }, - fakeAuthority + await AuthorityFactory.createDiscoveredInstance( + TEST_CONFIG.validAuthority, + new HttpClient(), + new MockStorageClass( + TEST_CONFIG.MSAL_CLIENT_ID, + cryptoProvider, + new Logger({}) + ), + { + protocolMode: ProtocolMode.AAD, + knownAuthorities: [], + cloudDiscoveryMetadata: "", + authorityMetadata: "", + }, + new Logger({}), + TEST_CONFIG.CORRELATION_ID + ) ); // @ts-ignore @@ -969,7 +955,10 @@ describe("PublicClientApplication", () => { const url = await authApp.getAuthCodeUrl(request); expect( url.startsWith( - DEFAULT_OPENID_CONFIG_RESPONSE.body.authorization_endpoint + DEFAULT_OPENID_CONFIG_RESPONSE.body.authorization_endpoint.replace( + "{tenant}", + "common" + ) ) ).toBe(true); expect(url).toContain(appConfig.auth.clientId); @@ -992,9 +981,6 @@ describe("PublicClientApplication", () => { const authApp = new PublicClientApplication(appConfig); await authApp.acquireTokenByUsernamePassword(request); expect(usernamePasswordClientSpy).toHaveBeenCalledTimes(1); - expect(usernamePasswordClientSpy).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireToken default authority", async () => { @@ -1013,32 +999,17 @@ describe("PublicClientApplication", () => { const mockRefreshTokenClient = getMsalCommonAutoMock().RefreshTokenClient; jest.spyOn(msalCommon, "RefreshTokenClient").mockImplementation( - (config) => new mockRefreshTokenClient(config) + (config) => { + expect(config.authOptions.authority.canonicalAuthority).toEqual( + TEST_CONSTANTS.DEFAULT_AUTHORITY + ); + return new mockRefreshTokenClient(config); + } ); - const authorityMock = - setupAuthorityFactory_createDiscoveredInstance_mock(fakeAuthority); - const authApp = new PublicClientApplication(config); await authApp.acquireTokenByRefreshToken(request); - expect(authorityMock.mock.calls[0][0]).toBe( - TEST_CONSTANTS.DEFAULT_AUTHORITY - ); - expect(authorityMock.mock.calls[0][1]).toBeInstanceOf(HttpClient); - expect(authorityMock.mock.calls[0][2]).toBeInstanceOf(NodeStorage); - expect(authorityMock.mock.calls[0][3]).toStrictEqual({ - protocolMode: ProtocolMode.AAD, - knownAuthorities: [], - azureRegionConfiguration: undefined, - cloudDiscoveryMetadata: "", - authorityMetadata: "", - skipAuthorityMetadataCache: false, - }); - expect(authorityMock.mock.calls[0][4]).toBeInstanceOf(Logger); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("authority overridden by acquire token request parameters", async () => { @@ -1052,32 +1023,17 @@ describe("PublicClientApplication", () => { const mockRefreshTokenClient = getMsalCommonAutoMock().RefreshTokenClient; jest.spyOn(msalCommon, "RefreshTokenClient").mockImplementation( - (config) => new mockRefreshTokenClient(config) + (config) => { + expect(config.authOptions.authority.canonicalAuthority).toEqual( + TEST_CONSTANTS.ALTERNATE_AUTHORITY + ); + return new mockRefreshTokenClient(config); + } ); - const authorityMock = - setupAuthorityFactory_createDiscoveredInstance_mock(); - const authApp = new PublicClientApplication(appConfig); await authApp.acquireTokenByRefreshToken(request); - expect(authorityMock.mock.calls[0][0]).toBe( - TEST_CONSTANTS.ALTERNATE_AUTHORITY - ); - expect(authorityMock.mock.calls[0][1]).toBeInstanceOf(HttpClient); - expect(authorityMock.mock.calls[0][2]).toBeInstanceOf(NodeStorage); - expect(authorityMock.mock.calls[0][3]).toStrictEqual({ - protocolMode: ProtocolMode.AAD, - knownAuthorities: [], - azureRegionConfiguration: undefined, - cloudDiscoveryMetadata: "", - authorityMetadata: "", - skipAuthorityMetadataCache: false, - }); - expect(authorityMock.mock.calls[0][4]).toBeInstanceOf(Logger); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireToken when azureCloudOptions are set", async () => { @@ -1101,32 +1057,17 @@ describe("PublicClientApplication", () => { const mockRefreshTokenClient = getMsalCommonAutoMock().RefreshTokenClient; jest.spyOn(msalCommon, "RefreshTokenClient").mockImplementation( - (config) => new mockRefreshTokenClient(config) + (config) => { + expect(config.authOptions.authority.canonicalAuthority).toEqual( + TEST_CONSTANTS.USGOV_AUTHORITY + ); + return new mockRefreshTokenClient(config); + } ); - const authorityMock = - setupAuthorityFactory_createDiscoveredInstance_mock(fakeAuthority); - const authApp = new PublicClientApplication(config); await authApp.acquireTokenByRefreshToken(request); - expect(authorityMock.mock.calls[0][0]).toBe( - TEST_CONSTANTS.USGOV_AUTHORITY - ); - expect(authorityMock.mock.calls[0][1]).toBeInstanceOf(HttpClient); - expect(authorityMock.mock.calls[0][2]).toBeInstanceOf(NodeStorage); - expect(authorityMock.mock.calls[0][3]).toStrictEqual({ - protocolMode: ProtocolMode.AAD, - knownAuthorities: [], - azureRegionConfiguration: undefined, - cloudDiscoveryMetadata: "", - authorityMetadata: "", - skipAuthorityMetadataCache: false, - }); - expect(authorityMock.mock.calls[0][4]).toBeInstanceOf(Logger); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("acquireToken when azureCloudOptions and authority are set", async () => { @@ -1151,32 +1092,17 @@ describe("PublicClientApplication", () => { const mockRefreshTokenClient = getMsalCommonAutoMock().RefreshTokenClient; jest.spyOn(msalCommon, "RefreshTokenClient").mockImplementation( - (config) => new mockRefreshTokenClient(config) + (config) => { + expect(config.authOptions.authority.canonicalAuthority).toEqual( + TEST_CONSTANTS.USGOV_AUTHORITY + ); + return new mockRefreshTokenClient(config); + } ); - const authorityMock = - setupAuthorityFactory_createDiscoveredInstance_mock(fakeAuthority); - const authApp = new PublicClientApplication(config); await authApp.acquireTokenByRefreshToken(request); - expect(authorityMock.mock.calls[0][0]).toBe( - TEST_CONSTANTS.USGOV_AUTHORITY - ); - expect(authorityMock.mock.calls[0][1]).toBeInstanceOf(HttpClient); - expect(authorityMock.mock.calls[0][2]).toBeInstanceOf(NodeStorage); - expect(authorityMock.mock.calls[0][3]).toStrictEqual({ - protocolMode: ProtocolMode.AAD, - knownAuthorities: [], - azureRegionConfiguration: undefined, - cloudDiscoveryMetadata: "", - authorityMetadata: "", - skipAuthorityMetadataCache: false, - }); - expect(authorityMock.mock.calls[0][4]).toBeInstanceOf(Logger); expect(RefreshTokenClient).toHaveBeenCalledTimes(1); - expect(RefreshTokenClient).toHaveBeenCalledWith( - expect.objectContaining(expectedConfig) - ); }); test("getLogger and setLogger", async () => { diff --git a/lib/msal-node/test/client/test-fixtures.ts b/lib/msal-node/test/client/test-fixtures.ts index 568c2fc7bb..c59af065ab 100644 --- a/lib/msal-node/test/client/test-fixtures.ts +++ b/lib/msal-node/test/client/test-fixtures.ts @@ -3,18 +3,9 @@ * Licensed under the MIT License. */ -import { - ServerTelemetryManager, - Authority, - AuthorityFactory, - ProtocolMode, -} from "@azure/msal-common"; +import { ServerTelemetryManager } from "@azure/msal-common"; import * as msalCommon from "@azure/msal-common"; -import { - DEFAULT_OPENID_CONFIG_RESPONSE, - TEST_CONSTANTS, -} from "../utils/TestConstants"; // @ts-ignore const mockServerTelemetryManager: ServerTelemetryManager = { @@ -48,39 +39,3 @@ export const setupServerTelemetryManagerMock = () => { return mockServerTelemetryManager; }; - -export const fakeAuthority: Authority = { - protocolMode: ProtocolMode.AAD, - regionDiscoveryMetadata: { - region_used: undefined, - region_source: undefined, - region_outcome: undefined, - }, - options: { - protocolMode: ProtocolMode.AAD, - knownAuthorities: [], - cloudDiscoveryMetadata: "", - authorityMetadata: "", - }, - authorizationEndpoint: - DEFAULT_OPENID_CONFIG_RESPONSE.body.authorization_endpoint, - resolveEndpointsAsync: () => { - return new Promise((resolve) => { - resolve(); - }); - }, - discoveryComplete: () => { - return true; - }, - getPreferredCache: () => { - return TEST_CONSTANTS.PREFERRED_CACHE; - }, -} as unknown as Authority; - -export const setupAuthorityFactory_createDiscoveredInstance_mock = ( - authority = fakeAuthority -): jest.SpyInstance => { - return jest - .spyOn(AuthorityFactory, "createDiscoveredInstance") - .mockReturnValue(Promise.resolve(authority)); -}; diff --git a/lib/msal-node/test/config/ClientConfiguration.spec.ts b/lib/msal-node/test/config/ClientConfiguration.spec.ts index 87be736804..42722ce5fa 100644 --- a/lib/msal-node/test/config/ClientConfiguration.spec.ts +++ b/lib/msal-node/test/config/ClientConfiguration.spec.ts @@ -3,10 +3,12 @@ import { Configuration, } from "../../src/config/Configuration"; import { HttpClient } from "../../src/network/HttpClient"; -import { TEST_CONSTANTS, AUTHENTICATION_RESULT } from "../utils/TestConstants"; import { - Authority, - AuthorityFactory, + TEST_CONSTANTS, + AUTHENTICATION_RESULT, + DEFAULT_OPENID_CONFIG_RESPONSE, +} from "../utils/TestConstants"; +import { LogLevel, NetworkRequestOptions, AzureCloudInstance, @@ -179,25 +181,6 @@ describe("ClientConfiguration tests", () => { }); test("client capabilities are handled as expected", async () => { - const authority: Authority = { - regionDiscoveryMetadata: { - region_used: undefined, - region_source: undefined, - region_outcome: undefined, - }, - resolveEndpointsAsync: () => { - return new Promise((resolve) => { - resolve(); - }); - }, - discoveryComplete: () => { - return true; - }, - getPreferredCache: () => { - return TEST_CONSTANTS.PREFERRED_CACHE; - }, - } as Authority; - const appConfig: Configuration = { auth: { clientId: TEST_CONSTANTS.CLIENT_ID, @@ -222,11 +205,6 @@ describe("ClientConfiguration tests", () => { skipCache: true, }; - jest.spyOn( - AuthorityFactory, - "createDiscoveredInstance" - ).mockReturnValue(Promise.resolve(authority)); - await new ConfidentialClientApplication( appConfig ).acquireTokenByClientCredential(request); @@ -234,7 +212,10 @@ describe("ClientConfiguration tests", () => { expect( appConfig.system?.networkClient?.sendPostRequestAsync ).toHaveBeenCalledWith( - undefined, + DEFAULT_OPENID_CONFIG_RESPONSE.body.token_endpoint.replace( + "{tenant}", + "tenantid" + ), expect.objectContaining({ body: expect.stringContaining("TEST-CAPABILITY"), }) @@ -242,25 +223,6 @@ describe("ClientConfiguration tests", () => { }); test("client capabilities are handled as expected for OBO flow", async () => { - const authority: Authority = { - regionDiscoveryMetadata: { - region_used: undefined, - region_source: undefined, - region_outcome: undefined, - }, - resolveEndpointsAsync: () => { - return new Promise((resolve) => { - resolve(); - }); - }, - discoveryComplete: () => { - return true; - }, - getPreferredCache: () => { - return TEST_CONSTANTS.PREFERRED_CACHE; - }, - } as Authority; - const oboRequest: OnBehalfOfRequest = { scopes: TEST_CONSTANTS.DEFAULT_GRAPH_SCOPE, oboAssertion: "user_assertion_hash", @@ -286,11 +248,6 @@ describe("ClientConfiguration tests", () => { }, }; - jest.spyOn( - AuthorityFactory, - "createDiscoveredInstance" - ).mockReturnValue(Promise.resolve(authority)); - await new ConfidentialClientApplication( appConfig ).acquireTokenOnBehalfOf(oboRequest); @@ -298,7 +255,10 @@ describe("ClientConfiguration tests", () => { expect( appConfig.system?.networkClient?.sendPostRequestAsync ).toHaveBeenCalledWith( - undefined, + DEFAULT_OPENID_CONFIG_RESPONSE.body.token_endpoint.replace( + "{tenant}", + "tenantid" + ), expect.objectContaining({ body: expect.stringContaining("TEST-CAPABILITY"), }) diff --git a/lib/msal-node/test/utils/TestConstants.ts b/lib/msal-node/test/utils/TestConstants.ts index 9e77c8bc76..e99ce727b6 100644 --- a/lib/msal-node/test/utils/TestConstants.ts +++ b/lib/msal-node/test/utils/TestConstants.ts @@ -19,7 +19,7 @@ export const TEST_CONSTANTS = { CLIENT_ID: "b41a6fbb-c728-4e03-aa59-d25b0fd383b6", DEFAULT_AUTHORITY: "https://login.microsoftonline.com/common/", AUTHORITY: "https://login.microsoftonline.com/TenantId", - ALTERNATE_AUTHORITY: "https://login.microsoftonline.com/alternate", + ALTERNATE_AUTHORITY: "https://login.microsoftonline.com/alternate/", USGOV_AUTHORITY: "https://login.microsoftonline.us/common/", REDIRECT_URI: "http://localhost:8080", CLIENT_SECRET: "MOCK_CLIENT_SECRET", diff --git a/samples/msal-browser-samples/VanillaJSTestApp2.0/app/default/authConfig.js b/samples/msal-browser-samples/VanillaJSTestApp2.0/app/default/authConfig.js index 994e563508..afb8e0933f 100644 --- a/samples/msal-browser-samples/VanillaJSTestApp2.0/app/default/authConfig.js +++ b/samples/msal-browser-samples/VanillaJSTestApp2.0/app/default/authConfig.js @@ -1,8 +1,9 @@ // Config object to be passed to Msal on creation const msalConfig = { auth: { - clientId: "ENTER_CLIENT_ID_HERE", - authority: "https://login.microsoftonline.com/ENTER_TENANT_ID_HERE", + clientId: "b5c2e510-4a17-4feb-b219-e55aa5b74144", + authority: + "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47", }, cache: { cacheLocation: "sessionStorage", // This configures where your cache will be stored @@ -51,17 +52,17 @@ const loginRequest = { // Add here the endpoints for MS Graph API services you would like to use. const graphConfig = { graphMeEndpoint: "https://graph.microsoft.com/v1.0/me", - graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages" + graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages", }; // Add here scopes for access token to be used at MS Graph API endpoints. const tokenRequest = { scopes: ["Mail.Read"], - forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token + forceRefresh: false, // Set this to "true" to skip a cached token and go to the server to get a new token }; const silentRequest = { - scopes: ["openid", "profile", "User.Read", "Mail.Read"] + scopes: ["openid", "profile", "User.Read", "Mail.Read"], }; -const logoutRequest = {} \ No newline at end of file +const logoutRequest = {};