Skip to content

Instance Discovery 2.x #1756

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f3b6117
Port changes from msal-core
tnorling Jun 5, 2020
7ae8baf
Merge branch 'dev' of https://github.com/AzureAD/microsoft-authentica…
tnorling Jun 18, 2020
6025e84
Add support for preferred_cache and preferred_network
tnorling Jun 18, 2020
7872ca2
Update references to old temp constant
tnorling Jun 18, 2020
dcaff8e
Merge branch 'dev' of https://github.com/AzureAD/microsoft-authentica…
tnorling Jun 18, 2020
a71e396
Cleanup getInstanceMetadata
tnorling Jun 18, 2020
b9d4e62
Cleanup
tnorling Jun 18, 2020
9d10e65
Update node and browser
tnorling Jun 18, 2020
2600876
Adding code for instance_aware authentication in msal-browser
pkanher617 Jun 19, 2020
5307fa8
Adding graph hostname and graph host to the auth result
pkanher617 Jun 19, 2020
710075d
Adding AuthCodePayload object
pkanher617 Jun 19, 2020
d96595f
Rename AuthCodeResponse file
pkanher617 Jun 19, 2020
b2c6aa7
Update PublicClientApplication.ts
pkanher617 Jun 19, 2020
53de8da
adding instance aware sample
pkanher617 Jun 19, 2020
171d4d0
Remove policy from createAccount
tnorling Jun 19, 2020
570b361
Update environment for adfs
tnorling Jun 19, 2020
55f7be5
All common tests passing
tnorling Jun 19, 2020
4aead0a
Browser tests passing
tnorling Jun 19, 2020
4f15a91
Add tests
tnorling Jun 19, 2020
4662361
Merge branch 'instance-aware-2.0' of https://github.com/AzureAD/micro…
tnorling Jun 19, 2020
0dddb02
Add error
tnorling Jun 19, 2020
ed17743
Update untrustedAuthority error message
tnorling Jun 19, 2020
27b0530
Address feedback
tnorling Jun 20, 2020
f939af1
Address feedback
tnorling Jun 20, 2020
045acbe
Revert VScode settings
tnorling Jun 20, 2020
da430bd
Revert VScode settings
tnorling Jun 20, 2020
663e604
Add performance doc
tnorling Jun 22, 2020
4d35732
Add performance doc
tnorling Jun 22, 2020
811121a
Revert "Add performance doc"
tnorling Jun 22, 2020
d4686bd
Revert "Add performance doc"
tnorling Jun 22, 2020
5552d53
Revert "Revert VScode settings"
tnorling Jun 22, 2020
d678d50
Revert "Revert VScode settings"
tnorling Jun 22, 2020
30a8394
Revert "Address feedback"
tnorling Jun 22, 2020
c5a88a9
Revert "Address feedback"
tnorling Jun 22, 2020
842a292
Revert "Update untrustedAuthority error message"
tnorling Jun 22, 2020
d89d5c6
Revert "Add error"
tnorling Jun 22, 2020
c326777
Revert "Merge branch 'instance-aware-2.0' of https://github.com/Azure…
tnorling Jun 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions lib/msal-browser/src/app/PublicClientApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
Authority,
AuthorityFactory,
InteractionRequiredAuthError,
B2cAuthority,
TrustedAuthority,
AuthorizationUrlRequest,
PersistentCacheKeys,
IdToken,
Expand Down Expand Up @@ -100,13 +100,9 @@ export class PublicClientApplication {
this.browserStorage = new BrowserStorage(this.config.auth.clientId, this.config.cache);

// Initialize default authority instance
B2cAuthority.setKnownAuthorities(this.config.auth.knownAuthorities);
TrustedAuthority.setTrustedAuthoritiesFromConfig(this.config.auth.knownAuthorities, this.config.auth.instanceMetadata);

this.defaultAuthorityPromise = AuthorityFactory.createDiscoveredInstance(
this.config.auth.authority,
this.networkClient,
true
);
this.defaultAuthorityPromise = AuthorityFactory.createDiscoveredInstance(this.config.auth.authority, this.networkClient, true);

// Check for hash and save response promise
this.tokenExchangePromise = this.handleRedirectResponse();
Expand Down Expand Up @@ -218,7 +214,7 @@ export class PublicClientApplication {
const interactionHandler = new RedirectHandler(authClient, this.browserStorage);
if (!StringUtils.isEmpty(responseHash)) {
// Hash contains known properties - handle and return in callback
return interactionHandler.handleCodeResponse(responseHash, this.browserCrypto);
return interactionHandler.handleCodeResponse(responseHash, this.networkClient, this.browserCrypto);
}

// There is no hash - assume we are in clean state and clear any current request data.
Expand Down Expand Up @@ -330,7 +326,7 @@ export class PublicClientApplication {
// Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
const hash = await interactionHandler.monitorWindowForHash(popupWindow, this.config.system.windowHashTimeout, navigateUrl);
// Handle response from hash string.
return await interactionHandler.handleCodeResponse(hash);
return await interactionHandler.handleCodeResponse(hash, this.networkClient);
}

// #endregion
Expand Down Expand Up @@ -453,7 +449,7 @@ export class PublicClientApplication {
// Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
const hash = await silentHandler.monitorFrameForHash(msalFrame, this.config.system.iframeHashTimeout, navigateUrl);
// Handle response from hash string.
return await silentHandler.handleCodeResponse(hash);
return await silentHandler.handleCodeResponse(hash, this.networkClient);
} catch (e) {
throw e;
}
Expand Down Expand Up @@ -576,8 +572,10 @@ export class PublicClientApplication {
* @param authorityUri
*/
private async getClientConfiguration(authorityUri?: string): Promise<ClientConfiguration> {
const discoveredAuthority = authorityUri ? await AuthorityFactory.createDiscoveredInstance(authorityUri, this.config.system.networkClient)
: await this.defaultAuthorityPromise;
const defaultAuthority = await this.defaultAuthorityPromise;
const shouldCreateAuthority = !!authorityUri && authorityUri !== defaultAuthority.canonicalAuthority;
const discoveredAuthority = shouldCreateAuthority ? await AuthorityFactory.createDiscoveredInstance(authorityUri, this.config.system.networkClient)
: defaultAuthority;
return {
authOptions: {
clientId: this.config.auth.clientId,
Expand Down
4 changes: 3 additions & 1 deletion lib/msal-browser/src/config/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { SystemOptions, LoggerOptions, INetworkModule, LogLevel, DEFAULT_SYSTEM_OPTIONS, Constants } from "@azure/msal-common";
import { SystemOptions, LoggerOptions, INetworkModule, LogLevel, DEFAULT_SYSTEM_OPTIONS, Constants, IInstanceDiscoveryMetadata } from "@azure/msal-common";
import { BrowserUtils } from "../utils/BrowserUtils";
import { BrowserConstants } from "../utils/BrowserConstants";

Expand All @@ -14,6 +14,7 @@ export type BrowserAuthOptions = {
clientId: string;
authority?: string;
knownAuthorities?: Array<string>;
instanceMetadata?: Array<IInstanceDiscoveryMetadata>;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming here might get confusing when we implement the other perf changes which introduced authorityMetadata in msal-core. Open to suggestions for a better name here.

redirectUri?: string | (() => string);
postLogoutRedirectUri?: string | (() => string);
navigateToLoginRequestUrl?: boolean;
Expand Down Expand Up @@ -67,6 +68,7 @@ const DEFAULT_AUTH_OPTIONS: BrowserAuthOptions = {
clientId: "",
authority: `${Constants.DEFAULT_AUTHORITY}/`,
knownAuthorities: [],
instanceMetadata: [],
redirectUri: () => BrowserUtils.getCurrentUri(),
postLogoutRedirectUri: () => BrowserUtils.getCurrentUri(),
navigateToLoginRequestUrl: true
Expand Down
20 changes: 15 additions & 5 deletions lib/msal-browser/src/interaction_handler/InteractionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { StringUtils, AuthorizationCodeRequest, CacheSchemaType, AuthenticationResult, AuthorizationCodeClient } from "@azure/msal-common";
import { StringUtils, AuthorizationCodeRequest, CacheSchemaType, AuthenticationResult, AuthorizationCodeClient, AuthorizationCodePayload, AuthorityFactory, INetworkModule } from "@azure/msal-common";
import { BrowserStorage } from "../cache/BrowserStorage";
import { BrowserAuthError } from "../error/BrowserAuthError";
import { TemporaryCacheKeys } from "../utils/BrowserConstants";
Expand Down Expand Up @@ -31,7 +31,7 @@ export abstract class InteractionHandler {
* Function to handle response parameters from hash.
* @param locationHash
*/
async handleCodeResponse(locationHash: string): Promise<AuthenticationResult> {
async handleCodeResponse(locationHash: string, networkModule: INetworkModule): Promise<AuthenticationResult> {
// Check that location hash isn't empty.
if (StringUtils.isEmpty(locationHash)) {
throw BrowserAuthError.createEmptyHashError(locationHash);
Expand All @@ -43,13 +43,23 @@ export abstract class InteractionHandler {
const cachedNonce = this.browserStorage.getItem(this.browserStorage.generateCacheKey(cachedNonceKey), CacheSchemaType.TEMPORARY) as string;

// Handle code response.
const authCode = this.authModule.handleFragmentResponse(locationHash, requestState);
const authCodeResponse: AuthorizationCodePayload = this.authModule.handleFragmentResponse(locationHash, requestState);

// Assign code to request
this.authCodeRequest.code = authCode;
this.authCodeRequest.code = authCodeResponse.code;
if (authCodeResponse.cloud_graph_host_name) {
const cloudInstanceAuthorityUri = `https://${authCodeResponse.cloud_instance_host_name}/common/`;
if (cloudInstanceAuthorityUri !== this.browserStorage.getCachedAuthority()) {
const cloudInstanceAuthority = await AuthorityFactory.createDiscoveredInstance(this.authCodeRequest.authority, networkModule, true);
this.authModule.updateAuthority(cloudInstanceAuthority);
}
}

authCodeResponse.nonce = cachedNonce;
authCodeResponse.state = requestState;

// Acquire token with retrieved code.
const tokenResponse = await this.authModule.acquireToken(this.authCodeRequest, cachedNonce, requestState);
const tokenResponse = await this.authModule.acquireToken(this.authCodeRequest, authCodeResponse);
this.browserStorage.cleanRequest();
return tokenResponse;
}
Expand Down
22 changes: 17 additions & 5 deletions lib/msal-browser/src/interaction_handler/RedirectHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { StringUtils, AuthorizationCodeRequest, ICrypto, CacheSchemaType, AuthenticationResult } from "@azure/msal-common";
import { StringUtils, AuthorizationCodeRequest, ICrypto, CacheSchemaType, AuthenticationResult, INetworkModule, AuthorityFactory, AuthorizationCodePayload } from "@azure/msal-common";
import { InteractionHandler } from "./InteractionHandler";
import { BrowserAuthError } from "../error/BrowserAuthError";
import { BrowserConstants, TemporaryCacheKeys } from "../utils/BrowserConstants";
Expand Down Expand Up @@ -46,7 +46,7 @@ export class RedirectHandler extends InteractionHandler {
* Handle authorization code response in the window.
* @param hash
*/
async handleCodeResponse(locationHash: string, browserCrypto?: ICrypto): Promise<AuthenticationResult> {
async handleCodeResponse(locationHash: string, networkModule: INetworkModule, browserCrypto?: ICrypto): Promise<AuthenticationResult> {
// Check that location hash isn't empty.
if (StringUtils.isEmpty(locationHash)) {
throw BrowserAuthError.createEmptyHashError(locationHash);
Expand All @@ -62,14 +62,26 @@ export class RedirectHandler extends InteractionHandler {
this.authCodeRequest = this.browserStorage.getCachedRequest(requestState, browserCrypto);

// Handle code response.
const authCode = this.authModule.handleFragmentResponse(locationHash, requestState);
this.authCodeRequest.code = authCode;
const authCodeResponse: AuthorizationCodePayload = this.authModule.handleFragmentResponse(locationHash, requestState);

// Assign code to request
this.authCodeRequest.code = authCodeResponse.code;
if (authCodeResponse.cloud_graph_host_name) {
const cloudInstanceAuthorityUri = `https://${authCodeResponse.cloud_instance_host_name}/common/`;
if (cloudInstanceAuthorityUri !== this.browserStorage.getCachedAuthority()) {
const cloudInstanceAuthority = await AuthorityFactory.createDiscoveredInstance(this.authCodeRequest.authority, networkModule, true);
this.authModule.updateAuthority(cloudInstanceAuthority);
}
}

authCodeResponse.nonce = cachedNonce;
authCodeResponse.state = requestState;

// Hash was processed successfully - remove from cache
this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH));

// Acquire token with retrieved code.
const tokenResponse = await this.authModule.acquireToken(this.authCodeRequest, cachedNonce, requestState);
const tokenResponse = await this.authModule.acquireToken(this.authCodeRequest, authCodeResponse);
this.browserStorage.cleanRequest();
return tokenResponse;
}
Expand Down
Loading