Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/microsoft-authentication/src/extensionV1.ts
3314 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 * as vscode from 'vscode';
7
import { Environment, EnvironmentParameters } from '@azure/ms-rest-azure-env';
8
import { AzureActiveDirectoryService, IStoredSession } from './AADHelper';
9
import { BetterTokenStorage } from './betterSecretStorage';
10
import { UriEventHandler } from './UriEventHandler';
11
import TelemetryReporter from '@vscode/extension-telemetry';
12
import Logger from './logger';
13
14
async function initMicrosoftSovereignCloudAuthProvider(context: vscode.ExtensionContext, telemetryReporter: TelemetryReporter, uriHandler: UriEventHandler, tokenStorage: BetterTokenStorage<IStoredSession>): Promise<vscode.Disposable | undefined> {
15
const environment = vscode.workspace.getConfiguration('microsoft-sovereign-cloud').get<string | undefined>('environment');
16
let authProviderName: string | undefined;
17
if (!environment) {
18
return undefined;
19
}
20
21
if (environment === 'custom') {
22
const customEnv = vscode.workspace.getConfiguration('microsoft-sovereign-cloud').get<EnvironmentParameters>('customEnvironment');
23
if (!customEnv) {
24
const res = await vscode.window.showErrorMessage(vscode.l10n.t('You must also specify a custom environment in order to use the custom environment auth provider.'), vscode.l10n.t('Open settings'));
25
if (res) {
26
await vscode.commands.executeCommand('workbench.action.openSettingsJson', 'microsoft-sovereign-cloud.customEnvironment');
27
}
28
return undefined;
29
}
30
try {
31
Environment.add(customEnv);
32
} catch (e) {
33
const res = await vscode.window.showErrorMessage(vscode.l10n.t('Error validating custom environment setting: {0}', e.message), vscode.l10n.t('Open settings'));
34
if (res) {
35
await vscode.commands.executeCommand('workbench.action.openSettings', 'microsoft-sovereign-cloud.customEnvironment');
36
}
37
return undefined;
38
}
39
authProviderName = customEnv.name;
40
} else {
41
authProviderName = environment;
42
}
43
44
const env = Environment.get(authProviderName);
45
if (!env) {
46
const res = await vscode.window.showErrorMessage(vscode.l10n.t('The environment `{0}` is not a valid environment.', authProviderName), vscode.l10n.t('Open settings'));
47
return undefined;
48
}
49
50
const aadService = new AzureActiveDirectoryService(
51
vscode.window.createOutputChannel(vscode.l10n.t('Microsoft Sovereign Cloud Authentication'), { log: true }),
52
context,
53
uriHandler,
54
tokenStorage,
55
telemetryReporter,
56
env);
57
await aadService.initialize();
58
59
const disposable = vscode.authentication.registerAuthenticationProvider('microsoft-sovereign-cloud', authProviderName, {
60
onDidChangeSessions: aadService.onDidChangeSessions,
61
getSessions: (scopes: string[]) => aadService.getSessions(scopes),
62
createSession: async (scopes: string[]) => {
63
try {
64
/* __GDPR__
65
"loginMicrosoftSovereignCloud" : {
66
"owner": "TylerLeonhardt",
67
"comment": "Used to determine the usage of the Microsoft Sovereign Cloud Auth Provider.",
68
"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }
69
}
70
*/
71
telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloud', {
72
// Get rid of guids from telemetry.
73
scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))),
74
});
75
76
return await aadService.createSession(scopes);
77
} catch (e) {
78
/* __GDPR__
79
"loginMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
80
*/
81
telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloudFailed');
82
83
throw e;
84
}
85
},
86
removeSession: async (id: string) => {
87
try {
88
/* __GDPR__
89
"logoutMicrosoftSovereignCloud" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }
90
*/
91
telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloud');
92
93
await aadService.removeSessionById(id);
94
} catch (e) {
95
/* __GDPR__
96
"logoutMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }
97
*/
98
telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloudFailed');
99
}
100
}
101
}, { supportsMultipleAccounts: true });
102
103
context.subscriptions.push(disposable);
104
return disposable;
105
}
106
107
export async function activate(context: vscode.ExtensionContext, telemetryReporter: TelemetryReporter) {
108
// If we ever activate the old flow, then mark that we will need to migrate when the user upgrades to v2.
109
// TODO: MSAL Migration. Remove this when we remove the old flow.
110
context.globalState.update('msalMigration', false);
111
112
const uriHandler = new UriEventHandler();
113
context.subscriptions.push(uriHandler);
114
const betterSecretStorage = new BetterTokenStorage<IStoredSession>('microsoft.login.keylist', context);
115
116
const loginService = new AzureActiveDirectoryService(
117
Logger,
118
context,
119
uriHandler,
120
betterSecretStorage,
121
telemetryReporter,
122
Environment.AzureCloud);
123
await loginService.initialize();
124
125
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider(
126
'microsoft',
127
'Microsoft',
128
{
129
onDidChangeSessions: loginService.onDidChangeSessions,
130
getSessions: (scopes: string[], options?: vscode.AuthenticationProviderSessionOptions) => loginService.getSessions(scopes, options),
131
createSession: async (scopes: string[], options?: vscode.AuthenticationProviderSessionOptions) => {
132
try {
133
/* __GDPR__
134
"login" : {
135
"owner": "TylerLeonhardt",
136
"comment": "Used to determine the usage of the Microsoft Auth Provider.",
137
"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }
138
}
139
*/
140
telemetryReporter.sendTelemetryEvent('login', {
141
// Get rid of guids from telemetry.
142
scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))),
143
});
144
145
return await loginService.createSession(scopes, options);
146
} catch (e) {
147
/* __GDPR__
148
"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
149
*/
150
telemetryReporter.sendTelemetryEvent('loginFailed');
151
152
throw e;
153
}
154
},
155
removeSession: async (id: string) => {
156
try {
157
/* __GDPR__
158
"logout" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }
159
*/
160
telemetryReporter.sendTelemetryEvent('logout');
161
162
await loginService.removeSessionById(id);
163
} catch (e) {
164
/* __GDPR__
165
"logoutFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }
166
*/
167
telemetryReporter.sendTelemetryEvent('logoutFailed');
168
}
169
}
170
},
171
{
172
supportsMultipleAccounts: true,
173
supportedAuthorizationServers: [
174
vscode.Uri.parse('https://login.microsoftonline.com/*'),
175
vscode.Uri.parse('https://login.microsoftonline.com/*/v2.0')
176
]
177
}
178
));
179
180
let microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, telemetryReporter, uriHandler, betterSecretStorage);
181
182
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(async e => {
183
if (e.affectsConfiguration('microsoft-sovereign-cloud')) {
184
microsoftSovereignCloudAuthProviderDisposable?.dispose();
185
microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, telemetryReporter, uriHandler, betterSecretStorage);
186
}
187
}));
188
189
return;
190
}
191
192
// this method is called when your extension is deactivated
193
export function deactivate() { }
194
195