Skip to content
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

feat: add support for GCC and other sovereign clouds #1928

Merged
merged 28 commits into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
70def15
feat: add support for configuring the base URL in the graph client
musale Nov 2, 2022
6493323
feat: add base-url attribute to Msal2Provider
musale Nov 2, 2022
7a6913e
refactor: use GraphEndpoint type instead of string
musale Nov 3, 2022
dec32b7
refactor: move validating base URL to utility function
musale Nov 3, 2022
2b6a4e6
fix: use new URL().origin to validate the base URL
musale Nov 3, 2022
da24b0a
feat: set baseURL when you initialize with clientID
musale Nov 3, 2022
4d3e4dd
feat: update the types on the declared variable
musale Nov 8, 2022
6c5e538
fix: cast string to GraphEndpoint type in validation
musale Nov 8, 2022
9e24392
feat: update MsalProvider to use base-url property
musale Nov 8, 2022
461d2cf
feat: update the ElectronProvider to set a baseURL
musale Nov 8, 2022
d5a9ba3
feat: add base url to Sharepoint provider
musale Nov 8, 2022
626ad5b
feat: add base-url attribute to TeamsMsal2Provider
musale Nov 8, 2022
31aee59
feat: add base-url attribute to TeamsMsalProvider
musale Nov 8, 2022
48b4bce
feat: add base-url attribute to TeamsFxProvider
musale Nov 8, 2022
9a7d2d1
feat: change to validating the baseUrl before initializing the client
musale Nov 8, 2022
7249fa1
refactor: set the baseURL default value in constractor
musale Nov 8, 2022
5f6970c
refactor: set the baseURL default value in constructor
musale Nov 8, 2022
65590a4
Merge branch 'next/fluentui' of github.com:microsoftgraph/microsoft-g…
musale Nov 8, 2022
e3debfd
feat: add base-url to the baseProvider
musale Nov 15, 2022
23fe581
refactor: remove re-declaration of property in base class
musale Nov 15, 2022
aaf3e1f
fix: validate base URL string in the IProvider
musale Nov 15, 2022
3e83174
Merge branch 'next/fluentui' of github.com:microsoftgraph/microsoft-g…
musale Dec 2, 2022
89133b2
fix: do the validation when setting the baseURL
musale Dec 2, 2022
62dcbbc
refactor/docs: use one check to get all accounts and document the exp…
musale Dec 2, 2022
e8c8c29
Merge branch 'musale/support-gcc' of github.com:microsoftgraph/micros…
musale Dec 2, 2022
7f0ca96
fix: remove duplicate import
musale Dec 2, 2022
10dc01f
fix: set licence text on all files
musale Dec 2, 2022
393a36c
fix: updaet the memberof value of the base provider
musale Dec 5, 2022
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
7 changes: 7 additions & 0 deletions packages/mgt-components/src/utils/FluentComponents.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

import { provideFluentDesignSystem } from '@fluentui/web-components';

const designSystem = provideFluentDesignSystem();
Expand Down
6 changes: 4 additions & 2 deletions packages/mgt-element/src/Graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TelemetryHandler
} from '@microsoft/microsoft-graph-client';

import { IGraph } from './IGraph';
import { IGraph, MICROSOFT_GRAPH_DEFAULT_ENDPOINT } from './IGraph';
import { IProvider } from './providers/IProvider';
import { Batch } from './utils/Batch';
import { ComponentMiddlewareOptions } from './utils/ComponentMiddlewareOptions';
Expand Down Expand Up @@ -155,8 +155,10 @@ export function createFromProvider(provider: IProvider, version?: string, compon
new HTTPMessageHandler()
];

let baseURL = provider.baseURL ? provider.baseURL : MICROSOFT_GRAPH_DEFAULT_ENDPOINT;
const client = Client.initWithMiddleware({
middleware: chainMiddleware(...middleware)
middleware: chainMiddleware(...middleware),
baseUrl: baseURL
});

const graph = new Graph(client, version);
Expand Down
32 changes: 32 additions & 0 deletions packages/mgt-element/src/IGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,35 @@ export interface IGraph {
*/
createBatch(): IBatch;
}

/**
* GraphEndpoint is a valid URL that is used to access the Graph.
*/
export type GraphEndpoint =
musale marked this conversation as resolved.
Show resolved Hide resolved
| 'https://graph.microsoft.com'
| 'https://graph.microsoft.us'
| 'https://dod-graph.microsoft.us'
| 'https://graph.microsoft.de'
| 'https://microsoftgraph.chinacloudapi.cn';

/**
* MICROSOFT_GRAPH_ENDPOINTS is a set of all the valid Graph URL endpoints.
*/
export const MICROSOFT_GRAPH_ENDPOINTS: Set<GraphEndpoint> = new Set<GraphEndpoint>();

/**
* MICROSOFT_GRAPH_DEFAULT_ENDPOINT is the default Graph endpoint that is silently set on
* the providers as the baseURL.
*/
export const MICROSOFT_GRAPH_DEFAULT_ENDPOINT: GraphEndpoint = 'https://graph.microsoft.com';

(() => {
gavinbarron marked this conversation as resolved.
Show resolved Hide resolved
const endpoints: GraphEndpoint[] = [
MICROSOFT_GRAPH_DEFAULT_ENDPOINT,
'https://graph.microsoft.us',
'https://dod-graph.microsoft.us',
'https://graph.microsoft.de',
'https://microsoftgraph.chinacloudapi.cn'
];
endpoints.forEach(endpoint => MICROSOFT_GRAPH_ENDPOINTS.add(endpoint));
})();
12 changes: 12 additions & 0 deletions packages/mgt-element/src/components/baseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { property } from 'lit/decorators.js';
import { MgtBaseComponent } from './baseComponent';
import { IProvider } from '../providers/IProvider';
import { GraphEndpoint } from '../IGraph';

/**
* Abstract implementation for provider component
Expand Down Expand Up @@ -65,6 +66,17 @@ export abstract class MgtBaseProvider extends MgtBaseComponent {
})
public dependsOn: MgtBaseProvider;

/**
* The base URL that should be used in the graph client config.
*
* @memberof MgtBaseProvider
*/
@property({
attribute: 'base-url',
type: String
})
public baseUrl: GraphEndpoint;
musale marked this conversation as resolved.
Show resolved Hide resolved

private _provider: IProvider;

/**
Expand Down
20 changes: 19 additions & 1 deletion packages/mgt-element/src/providers/IProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import { AuthenticationProvider, AuthenticationProviderOptions } from '@microsoft/microsoft-graph-client';
import { IGraph } from '../IGraph';
import { validateBaseURL } from '../utils/GraphHelpers';
import { GraphEndpoint, IGraph, MICROSOFT_GRAPH_DEFAULT_ENDPOINT } from '../IGraph';
import { EventDispatcher, EventHandler } from '../utils/EventDispatcher';

/**
Expand Down Expand Up @@ -48,6 +49,23 @@ export abstract class IProvider implements AuthenticationProvider {
private _state: ProviderState;
private _loginChangedDispatcher = new EventDispatcher<LoginChangedEvent>();
private _activeAccountChangedDispatcher = new EventDispatcher<ActiveAccountChanged>();
private _baseURL: GraphEndpoint = MICROSOFT_GRAPH_DEFAULT_ENDPOINT;

/**
* The base URL to be used in the graph client config.
*/
public set baseURL(url: GraphEndpoint) {
if (validateBaseURL(url)) {
musale marked this conversation as resolved.
Show resolved Hide resolved
this._baseURL = url;
return;
} else {
throw new Error(`${url} is not a valid Graph URL endpoint.`);
}
}

public get baseURL(): GraphEndpoint {
return this._baseURL;
}

/**
* Enable/Disable incremental consent
Expand Down
19 changes: 18 additions & 1 deletion packages/mgt-element/src/utils/GraphHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { AuthenticationHandlerOptions, Middleware } from '@microsoft/microsoft-graph-client';
import { Providers } from '..';
import { GraphEndpoint, MICROSOFT_GRAPH_ENDPOINTS, Providers } from '..';

/**
* creates an AuthenticationHandlerOptions from scopes array that
Expand Down Expand Up @@ -46,3 +46,20 @@ export function chainMiddleware(...middleware: Middleware[]): Middleware {
}
return rootMiddleware;
}

/**
* Helper method to validate a base URL string
* @param url a URL string
* @returns GraphEndpoint
*/
export function validateBaseURL(url: string): GraphEndpoint {
try {
const urlObj = new URL(url);
const originAsEndpoint = urlObj.origin as GraphEndpoint;
if (MICROSOFT_GRAPH_ENDPOINTS.has(originAsEndpoint)) {
return originAsEndpoint;
}
} catch (error) {
return;
}
}
7 changes: 7 additions & 0 deletions packages/mgt-spfx/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

export { MgtLibrary } from './libraries/mgt/MgtLibrary';
export * from '@microsoft/mgt-sharepoint-provider';
export * from '@microsoft/mgt-components';
Expand Down
7 changes: 7 additions & 0 deletions packages/mgt-spfx/src/libraries/mgt/MgtLibrary.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

export class MgtLibrary {
public name(): string {
return 'MgtLibrary';
Expand Down
7 changes: 7 additions & 0 deletions packages/mgt-spfx/src/libraries/mgt/loc/en-us.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

define([], function() {
return {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
PublicClientApplication
} from '@azure/msal-node';
import { AuthenticationProviderOptions } from '@microsoft/microsoft-graph-client';
import { GraphEndpoint } from '@microsoft/mgt-element';
import { BrowserWindow, ipcMain } from 'electron';
import { CustomFileProtocolListener } from './CustomFileProtocol';
import { REDIRECT_URI, COMMON_AUTHORITY_URL } from './Constants';
Expand Down Expand Up @@ -65,6 +66,10 @@ export interface MsalElectronConfig {
* @memberof MsalElectronConfig
*/
cachePlugin?: ICachePlugin;
/**
* The base URL for the graph client
*/
baseURL?: GraphEndpoint;
}

/**
Expand All @@ -86,6 +91,11 @@ enum AuthState {
LOGGED_OUT = 'logged_out'
}

/**
* AccountDetails defines the available AccountInfo or undefined.
*/
type AccountDetails = AccountInfo | undefined;
musale marked this conversation as resolved.
Show resolved Hide resolved

/**
* ElectronAuthenticator class to be instantiated in the main process.
* Responsible for MSAL authentication flow and token acqusition.
Expand Down Expand Up @@ -133,10 +143,10 @@ export class ElectronAuthenticator {
* Logged in account
*
* @private
* @type {AccountInfo}
* @type {AccountDetails}
* @memberof ElectronAuthenticator
*/
private account: AccountInfo;
private account: AccountDetails;

/**
* Params to generate the URL for MSAL auth
Expand Down Expand Up @@ -182,7 +192,7 @@ export class ElectronAuthenticator {
*/
private constructor(config: MsalElectronConfig) {
this.setConfig(config);
this.account = null;
this.account = undefined;
this.mainWindow = config.mainWindow;
this.setRequestObjects(config.scopes);
this.setupProvider();
Expand Down Expand Up @@ -224,7 +234,7 @@ export class ElectronAuthenticator {
clientId: config.clientId,
authority: config.authority ? config.authority : COMMON_AUTHORITY_URL
},
cache: config.cachePlugin ? { cachePlugin: config.cachePlugin } : null,
cache: config.cachePlugin ? { cachePlugin: config.cachePlugin } : undefined,
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {},
Expand Down Expand Up @@ -255,7 +265,7 @@ export class ElectronAuthenticator {
this.authCodeRequest = {
scopes: requestScopes,
redirectUri,
code: null
code: ''
};
}

Expand Down Expand Up @@ -311,7 +321,7 @@ export class ElectronAuthenticator {
* @return {*} {Promise<string>}
* @memberof ElectronAuthenticator
*/
protected async getAccessToken(options?: AuthenticationProviderOptions): Promise<string> {
protected async getAccessToken(options?: AuthenticationProviderOptions): Promise<string | undefined> {
let authResponse;
const scopes = options && options.scopes ? options.scopes : this.authCodeUrlParams.scopes;
const account = this.account || (await this.getAccount());
Expand All @@ -326,6 +336,7 @@ export class ElectronAuthenticator {
if (authResponse) {
return authResponse.accessToken;
}
return undefined;
}

/**
Expand All @@ -337,7 +348,7 @@ export class ElectronAuthenticator {
* @return {*} {Promise<AuthenticationResult>}
* @memberof ElectronAuthenticator
*/
protected async getTokenSilent(tokenRequest, scopes?): Promise<AuthenticationResult> {
protected async getTokenSilent(tokenRequest, scopes?): Promise<AuthenticationResult | null> {
try {
return await this.clientApplication.acquireTokenSilent(tokenRequest);
} catch (error) {
Expand Down Expand Up @@ -366,7 +377,7 @@ export class ElectronAuthenticator {
protected async logout(): Promise<void> {
if (this.account) {
await this.clientApplication.getTokenCache().removeAccount(this.account);
this.account = null;
this.account = undefined;
}
}

Expand All @@ -379,8 +390,8 @@ export class ElectronAuthenticator {
* @memberof ElectronAuthenticator
*/
private async setAccountFromResponse(response: AuthenticationResult) {
if (response !== null) {
this.account = response.account;
if (response) {
this.account = response?.account || undefined;
} else {
this.account = await this.getAccount();
}
Expand Down Expand Up @@ -412,7 +423,7 @@ export class ElectronAuthenticator {
.acquireTokenByCode({
...this.authCodeRequest,
scopes: requestScopes,
code: authCode
code: authCode || ''
})
.catch((e: AuthError) => {
throw e;
Expand All @@ -429,7 +440,7 @@ export class ElectronAuthenticator {
* @return {*} {Promise<string>}
* @memberof ElectronAuthenticator
*/
private async listenForAuthCode(navigateUrl: string, prompt_type: promptType): Promise<string> {
private async listenForAuthCode(navigateUrl: string, prompt_type: promptType): Promise<string | null> {
this.setAuthWindow(true);
await this.authWindow.loadURL(navigateUrl);
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -474,20 +485,12 @@ export class ElectronAuthenticator {
* @return {*} {Promise<AccountInfo>}
* @memberof ElectronAuthenticator
*/
private async getAccount(): Promise<AccountInfo> {
private async getAccount(): Promise<AccountDetails> {
const cache = this.clientApplication.getTokenCache();
const currentAccounts = await cache.getAllAccounts();

if (currentAccounts === null) {
return null;
}

if (currentAccounts.length > 1) {
if (currentAccounts?.length >= 1) {
return currentAccounts[0];
} else if (currentAccounts.length === 1) {
return currentAccounts[0];
} else {
return null;
}
return undefined;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
* -------------------------------------------------------------------------------------------
*/

import { IProvider, Providers, ProviderState, createFromProvider } from '@microsoft/mgt-element';
import {
IProvider,
Providers,
ProviderState,
createFromProvider,
GraphEndpoint,
MICROSOFT_GRAPH_DEFAULT_ENDPOINT
} from '@microsoft/mgt-element';
import { AuthenticationProviderOptions } from '@microsoft/microsoft-graph-client';
import { ipcRenderer } from 'electron';

Expand All @@ -28,8 +35,9 @@ export class ElectronProvider extends IProvider {
return 'MgtElectronProvider';
}

constructor() {
constructor(baseUrl: GraphEndpoint = MICROSOFT_GRAPH_DEFAULT_ENDPOINT) {
super();
this.baseURL = baseUrl;
this.graph = createFromProvider(this);
this.setupProvider();
}
Expand Down
Loading