Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/microsoft-authentication/src/node/flows.ts
3320 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { AuthenticationResult } from '@azure/msal-node';
7
import { Uri, LogOutputChannel, env } from 'vscode';
8
import { ICachedPublicClientApplication } from '../common/publicClientCache';
9
import { UriHandlerLoopbackClient } from '../common/loopbackClientAndOpener';
10
import { UriEventHandler } from '../UriEventHandler';
11
import { loopbackTemplate } from './loopbackTemplate';
12
import { Config } from '../common/config';
13
14
const DEFAULT_REDIRECT_URI = 'https://vscode.dev/redirect';
15
16
export const enum ExtensionHost {
17
WebWorker,
18
Remote,
19
Local
20
}
21
22
interface IMsalFlowOptions {
23
supportsRemoteExtensionHost: boolean;
24
supportsWebWorkerExtensionHost: boolean;
25
}
26
27
interface IMsalFlowTriggerOptions {
28
cachedPca: ICachedPublicClientApplication;
29
authority: string;
30
scopes: string[];
31
loginHint?: string;
32
windowHandle?: Buffer;
33
logger: LogOutputChannel;
34
uriHandler: UriEventHandler;
35
claims?: string;
36
}
37
38
interface IMsalFlow {
39
readonly label: string;
40
readonly options: IMsalFlowOptions;
41
trigger(options: IMsalFlowTriggerOptions): Promise<AuthenticationResult>;
42
}
43
44
class DefaultLoopbackFlow implements IMsalFlow {
45
label = 'default';
46
options: IMsalFlowOptions = {
47
supportsRemoteExtensionHost: false,
48
supportsWebWorkerExtensionHost: false
49
};
50
51
async trigger({ cachedPca, authority, scopes, claims, loginHint, windowHandle, logger }: IMsalFlowTriggerOptions): Promise<AuthenticationResult> {
52
logger.info('Trying default msal flow...');
53
let redirectUri: string | undefined;
54
if (cachedPca.isBrokerAvailable && process.platform === 'darwin') {
55
redirectUri = Config.macOSBrokerRedirectUri;
56
}
57
return await cachedPca.acquireTokenInteractive({
58
openBrowser: async (url: string) => { await env.openExternal(Uri.parse(url)); },
59
scopes,
60
authority,
61
successTemplate: loopbackTemplate,
62
errorTemplate: loopbackTemplate,
63
loginHint,
64
prompt: loginHint ? undefined : 'select_account',
65
windowHandle,
66
claims,
67
});
68
}
69
}
70
71
class UrlHandlerFlow implements IMsalFlow {
72
label = 'protocol handler';
73
options: IMsalFlowOptions = {
74
supportsRemoteExtensionHost: true,
75
supportsWebWorkerExtensionHost: false
76
};
77
78
async trigger({ cachedPca, authority, scopes, claims, loginHint, windowHandle, logger, uriHandler }: IMsalFlowTriggerOptions): Promise<AuthenticationResult> {
79
logger.info('Trying protocol handler flow...');
80
const loopbackClient = new UriHandlerLoopbackClient(uriHandler, DEFAULT_REDIRECT_URI, logger);
81
let redirectUri: string | undefined;
82
if (cachedPca.isBrokerAvailable && process.platform === 'darwin') {
83
redirectUri = Config.macOSBrokerRedirectUri;
84
}
85
return await cachedPca.acquireTokenInteractive({
86
openBrowser: (url: string) => loopbackClient.openBrowser(url),
87
scopes,
88
authority,
89
loopbackClient,
90
loginHint,
91
prompt: loginHint ? undefined : 'select_account',
92
windowHandle,
93
claims,
94
});
95
}
96
}
97
98
const allFlows: IMsalFlow[] = [
99
new DefaultLoopbackFlow(),
100
new UrlHandlerFlow()
101
];
102
103
export interface IMsalFlowQuery {
104
extensionHost: ExtensionHost;
105
isBrokerSupported: boolean;
106
}
107
108
export function getMsalFlows(query: IMsalFlowQuery): IMsalFlow[] {
109
const flows = [];
110
for (const flow of allFlows) {
111
let useFlow: boolean = true;
112
switch (query.extensionHost) {
113
case ExtensionHost.Remote:
114
useFlow &&= flow.options.supportsRemoteExtensionHost;
115
break;
116
case ExtensionHost.WebWorker:
117
useFlow &&= flow.options.supportsWebWorkerExtensionHost;
118
break;
119
}
120
if (useFlow) {
121
flows.push(flow);
122
if (query.isBrokerSupported) {
123
// If broker is supported, only use the first valid flow
124
return flows;
125
}
126
}
127
}
128
return flows;
129
}
130
131