Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/authentication/common/authentication.ts
3296 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
import { Event } from '../../../../base/common/event.js';
6
import { IDisposable } from '../../../../base/common/lifecycle.js';
7
import { IAuthenticationChallenge, IAuthorizationProtectedResourceMetadata, IAuthorizationServerMetadata } from '../../../../base/common/oauth.js';
8
import { URI } from '../../../../base/common/uri.js';
9
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
10
11
/**
12
* Use this if you don't want the onDidChangeSessions event to fire in the extension host
13
*/
14
export const INTERNAL_AUTH_PROVIDER_PREFIX = '__';
15
16
export interface AuthenticationSessionAccount {
17
label: string;
18
id: string;
19
}
20
21
export interface AuthenticationSession {
22
id: string;
23
accessToken: string;
24
account: AuthenticationSessionAccount;
25
scopes: ReadonlyArray<string>;
26
idToken?: string;
27
}
28
29
export interface AuthenticationSessionsChangeEvent {
30
added: ReadonlyArray<AuthenticationSession> | undefined;
31
removed: ReadonlyArray<AuthenticationSession> | undefined;
32
changed: ReadonlyArray<AuthenticationSession> | undefined;
33
}
34
35
export interface AuthenticationProviderInformation {
36
id: string;
37
label: string;
38
authorizationServerGlobs?: ReadonlyArray<string>;
39
}
40
41
/**
42
* Options for creating an authentication session via the service.
43
*/
44
export interface IAuthenticationCreateSessionOptions {
45
activateImmediate?: boolean;
46
/**
47
* The account that is being asked about. If this is passed in, the provider should
48
* attempt to return the sessions that are only related to this account.
49
*/
50
account?: AuthenticationSessionAccount;
51
/**
52
* The authorization server URI to use for this creation request. If passed in, first we validate that
53
* the provider can use this authorization server, then it is passed down to the auth provider.
54
*/
55
authorizationServer?: URI;
56
/**
57
* Allows the authentication provider to take in additional parameters.
58
* It is up to the provider to define what these parameters are and handle them.
59
* This is useful for passing in additional information that is specific to the provider
60
* and not part of the standard authentication flow.
61
*/
62
[key: string]: any;
63
}
64
65
export interface IAuthenticationWWWAuthenticateRequest {
66
/**
67
* The raw WWW-Authenticate header value that triggered this challenge.
68
* This will be parsed by the authentication provider to extract the necessary
69
* challenge information.
70
*/
71
readonly wwwAuthenticate: string;
72
73
/**
74
* Optional scopes for the session. If not provided, the authentication provider
75
* may use default scopes or extract them from the challenge.
76
*/
77
readonly scopes?: readonly string[];
78
}
79
80
export function isAuthenticationWWWAuthenticateRequest(obj: unknown): obj is IAuthenticationWWWAuthenticateRequest {
81
return typeof obj === 'object'
82
&& obj !== null
83
&& 'wwwAuthenticate' in obj
84
&& (typeof obj.wwwAuthenticate === 'string');
85
}
86
87
/**
88
* Represents constraints for authentication, including challenges and optional scopes.
89
* This is used when creating or retrieving sessions that must satisfy specific authentication
90
* requirements from WWW-Authenticate headers.
91
*/
92
export interface IAuthenticationConstraint {
93
/**
94
* Array of authentication challenges parsed from WWW-Authenticate headers.
95
*/
96
readonly challenges: readonly IAuthenticationChallenge[];
97
98
/**
99
* Optional scopes for the session. If not provided, the authentication provider
100
* may extract scopes from the challenges or use default scopes.
101
*/
102
readonly scopes?: readonly string[];
103
}
104
105
/**
106
* Options for getting authentication sessions via the service.
107
*/
108
export interface IAuthenticationGetSessionsOptions {
109
/**
110
* The account that is being asked about. If this is passed in, the provider should
111
* attempt to return the sessions that are only related to this account.
112
*/
113
account?: AuthenticationSessionAccount;
114
/**
115
* The authorization server URI to use for this request. If passed in, first we validate that
116
* the provider can use this authorization server, then it is passed down to the auth provider.
117
*/
118
authorizationServer?: URI;
119
/**
120
* Allows the authentication provider to take in additional parameters.
121
* It is up to the provider to define what these parameters are and handle them.
122
* This is useful for passing in additional information that is specific to the provider
123
* and not part of the standard authentication flow.
124
*/
125
[key: string]: any;
126
}
127
128
export interface AllowedExtension {
129
id: string;
130
name: string;
131
/**
132
* If true or undefined, the extension is allowed to use the account
133
* If false, the extension is not allowed to use the account
134
* TODO: undefined shouldn't be a valid value, but it is for now
135
*/
136
allowed?: boolean;
137
lastUsed?: number;
138
// If true, this comes from the product.json
139
trusted?: boolean;
140
}
141
142
export interface IAuthenticationProviderHostDelegate {
143
/** Priority for this delegate, delegates are tested in descending priority order */
144
readonly priority: number;
145
create(authorizationServer: URI, serverMetadata: IAuthorizationServerMetadata, resource: IAuthorizationProtectedResourceMetadata | undefined): Promise<string>;
146
}
147
148
export const IAuthenticationService = createDecorator<IAuthenticationService>('IAuthenticationService');
149
150
export interface IAuthenticationService {
151
readonly _serviceBrand: undefined;
152
153
/**
154
* Fires when an authentication provider has been registered
155
*/
156
readonly onDidRegisterAuthenticationProvider: Event<AuthenticationProviderInformation>;
157
/**
158
* Fires when an authentication provider has been unregistered
159
*/
160
readonly onDidUnregisterAuthenticationProvider: Event<AuthenticationProviderInformation>;
161
162
/**
163
* Fires when the list of sessions for a provider has been added, removed or changed
164
*/
165
readonly onDidChangeSessions: Event<{ providerId: string; label: string; event: AuthenticationSessionsChangeEvent }>;
166
167
/**
168
* Fires when the list of declaredProviders has changed
169
*/
170
readonly onDidChangeDeclaredProviders: Event<void>;
171
172
/**
173
* All providers that have been statically declared by extensions. These may not actually be registered or active yet.
174
*/
175
readonly declaredProviders: AuthenticationProviderInformation[];
176
177
/**
178
* Registers that an extension has declared an authentication provider in their package.json
179
* @param provider The provider information to register
180
*/
181
registerDeclaredAuthenticationProvider(provider: AuthenticationProviderInformation): void;
182
183
/**
184
* Unregisters a declared authentication provider
185
* @param id The id of the provider to unregister
186
*/
187
unregisterDeclaredAuthenticationProvider(id: string): void;
188
189
/**
190
* Checks if an authentication provider has been registered
191
* @param id The id of the provider to check
192
*/
193
isAuthenticationProviderRegistered(id: string): boolean;
194
195
/**
196
* Checks if an authentication provider is dynamic
197
* @param id The id of the provider to check
198
*/
199
isDynamicAuthenticationProvider(id: string): boolean;
200
201
/**
202
* Registers an authentication provider
203
* @param id The id of the provider
204
* @param provider The implementation of the provider
205
*/
206
registerAuthenticationProvider(id: string, provider: IAuthenticationProvider): void;
207
208
/**
209
* Unregisters an authentication provider
210
* @param id The id of the provider to unregister
211
*/
212
unregisterAuthenticationProvider(id: string): void;
213
214
/**
215
* Gets the provider ids of all registered authentication providers
216
*/
217
getProviderIds(): string[];
218
219
/**
220
* Gets the provider with the given id.
221
* @param id The id of the provider to get
222
* @throws if the provider is not registered
223
*/
224
getProvider(id: string): IAuthenticationProvider;
225
226
/**
227
* Gets all accounts that are currently logged in across all sessions
228
* @param id The id of the provider to ask for accounts
229
* @returns A promise that resolves to an array of accounts
230
*/
231
getAccounts(id: string): Promise<ReadonlyArray<AuthenticationSessionAccount>>;
232
233
/**
234
* Gets all sessions that satisfy the given scopes from the provider with the given id
235
* @param id The id of the provider to ask for a session
236
* @param scopes The scopes for the session
237
* @param options Additional options for getting sessions
238
* @param activateImmediate If true, the provider should activate immediately if it is not already
239
*/
240
getSessions(id: string, scopeListOrRequest?: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate?: boolean): Promise<ReadonlyArray<AuthenticationSession>>;
241
242
/**
243
* Creates an AuthenticationSession with the given provider and scopes
244
* @param providerId The id of the provider
245
* @param scopes The scopes to request
246
* @param options Additional options for creating the session
247
*/
248
createSession(providerId: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise<AuthenticationSession>;
249
250
/**
251
* Removes the session with the given id from the provider with the given id
252
* @param providerId The id of the provider
253
* @param sessionId The id of the session to remove
254
*/
255
removeSession(providerId: string, sessionId: string): Promise<void>;
256
257
/**
258
* Gets a provider id for a specified authorization server
259
* @param authorizationServer The authorization server url that this provider is responsible for
260
*/
261
getOrActivateProviderIdForServer(authorizationServer: URI): Promise<string | undefined>;
262
263
/**
264
* Allows the ability register a delegate that will be used to start authentication providers
265
* @param delegate The delegate to register
266
*/
267
registerAuthenticationProviderHostDelegate(delegate: IAuthenticationProviderHostDelegate): IDisposable;
268
269
/**
270
* Creates a dynamic authentication provider for the given server metadata
271
* @param serverMetadata The metadata for the server that is being authenticated against
272
*/
273
createDynamicAuthenticationProvider(authorizationServer: URI, serverMetadata: IAuthorizationServerMetadata, resourceMetadata: IAuthorizationProtectedResourceMetadata | undefined): Promise<IAuthenticationProvider | undefined>;
274
}
275
276
export function isAuthenticationSession(thing: unknown): thing is AuthenticationSession {
277
if (typeof thing !== 'object' || !thing) {
278
return false;
279
}
280
const maybe = thing as AuthenticationSession;
281
if (typeof maybe.id !== 'string') {
282
return false;
283
}
284
if (typeof maybe.accessToken !== 'string') {
285
return false;
286
}
287
if (typeof maybe.account !== 'object' || !maybe.account) {
288
return false;
289
}
290
if (typeof maybe.account.label !== 'string') {
291
return false;
292
}
293
if (typeof maybe.account.id !== 'string') {
294
return false;
295
}
296
if (!Array.isArray(maybe.scopes)) {
297
return false;
298
}
299
if (maybe.idToken && typeof maybe.idToken !== 'string') {
300
return false;
301
}
302
return true;
303
}
304
305
// TODO: Move this into MainThreadAuthentication
306
export const IAuthenticationExtensionsService = createDecorator<IAuthenticationExtensionsService>('IAuthenticationExtensionsService');
307
export interface IAuthenticationExtensionsService {
308
readonly _serviceBrand: undefined;
309
310
/**
311
* Fires when an account preference for a specific provider has changed for the specified extensions. Does not fire when:
312
* * An account preference is removed
313
* * A session preference is changed (because it's deprecated)
314
* * A session preference is removed (because it's deprecated)
315
*/
316
onDidChangeAccountPreference: Event<{ extensionIds: string[]; providerId: string }>;
317
/**
318
* Returns the accountName (also known as account.label) to pair with `IAuthenticationAccessService` to get the account preference
319
* @param providerId The authentication provider id
320
* @param extensionId The extension id to get the preference for
321
* @returns The accountName of the preference, or undefined if there is no preference set
322
*/
323
getAccountPreference(extensionId: string, providerId: string): string | undefined;
324
/**
325
* Sets the account preference for the given provider and extension
326
* @param providerId The authentication provider id
327
* @param extensionId The extension id to set the preference for
328
* @param account The account to set the preference to
329
*/
330
updateAccountPreference(extensionId: string, providerId: string, account: AuthenticationSessionAccount): void;
331
/**
332
* Removes the account preference for the given provider and extension
333
* @param providerId The authentication provider id
334
* @param extensionId The extension id to remove the preference for
335
*/
336
removeAccountPreference(extensionId: string, providerId: string): void;
337
/**
338
* @deprecated Sets the session preference for the given provider and extension
339
* @param providerId
340
* @param extensionId
341
* @param session
342
*/
343
updateSessionPreference(providerId: string, extensionId: string, session: AuthenticationSession): void;
344
/**
345
* @deprecated Gets the session preference for the given provider and extension
346
* @param providerId
347
* @param extensionId
348
* @param scopes
349
*/
350
getSessionPreference(providerId: string, extensionId: string, scopes: string[]): string | undefined;
351
/**
352
* @deprecated Removes the session preference for the given provider and extension
353
* @param providerId
354
* @param extensionId
355
* @param scopes
356
*/
357
removeSessionPreference(providerId: string, extensionId: string, scopes: string[]): void;
358
selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): Promise<AuthenticationSession>;
359
requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): void;
360
requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string): Promise<void>;
361
updateNewSessionRequests(providerId: string, addedSessions: readonly AuthenticationSession[]): void;
362
}
363
364
/**
365
* Options passed to the authentication provider when asking for sessions.
366
*/
367
export interface IAuthenticationProviderSessionOptions {
368
/**
369
* The account that is being asked about. If this is passed in, the provider should
370
* attempt to return the sessions that are only related to this account.
371
*/
372
account?: AuthenticationSessionAccount;
373
/**
374
* The authorization server that is being asked about. If this is passed in, the provider should
375
* attempt to return sessions that are only related to this authorization server.
376
*/
377
authorizationServer?: URI;
378
/**
379
* Allows the authentication provider to take in additional parameters.
380
* It is up to the provider to define what these parameters are and handle them.
381
* This is useful for passing in additional information that is specific to the provider
382
* and not part of the standard authentication flow.
383
*/
384
[key: string]: any;
385
}
386
387
/**
388
* Represents an authentication provider.
389
*/
390
export interface IAuthenticationProvider {
391
/**
392
* The unique identifier of the authentication provider.
393
*/
394
readonly id: string;
395
396
/**
397
* The display label of the authentication provider.
398
*/
399
readonly label: string;
400
401
/**
402
* The resolved authorization servers. These can still contain globs, but should be concrete URIs
403
*/
404
readonly authorizationServers?: ReadonlyArray<URI>;
405
406
/**
407
* Indicates whether the authentication provider supports multiple accounts.
408
*/
409
readonly supportsMultipleAccounts: boolean;
410
411
/**
412
* Optional function to provide a custom confirmation message for authentication prompts.
413
* If not implemented, the default confirmation messages will be used.
414
* @param extensionName - The name of the extension requesting authentication.
415
* @param recreatingSession - Whether this is recreating an existing session.
416
* @returns A custom confirmation message or undefined to use the default message.
417
*/
418
readonly confirmation?: (extensionName: string, recreatingSession: boolean) => string | undefined;
419
420
/**
421
* An {@link Event} which fires when the array of sessions has changed, or data
422
* within a session has changed.
423
*/
424
readonly onDidChangeSessions: Event<AuthenticationSessionsChangeEvent>;
425
426
/**
427
* Retrieves a list of authentication sessions.
428
* @param scopes - An optional list of scopes. If provided, the sessions returned should match these permissions, otherwise all sessions should be returned.
429
* @param options - Additional options for getting sessions.
430
* @returns A promise that resolves to an array of authentication sessions.
431
*/
432
getSessions(scopes: string[] | undefined, options: IAuthenticationProviderSessionOptions): Promise<readonly AuthenticationSession[]>;
433
434
/**
435
* Prompts the user to log in.
436
* If login is successful, the `onDidChangeSessions` event should be fired.
437
* If login fails, a rejected promise should be returned.
438
* If the provider does not support multiple accounts, this method should not be called if there is already an existing session matching the provided scopes.
439
* @param scopes - A list of scopes that the new session should be created with.
440
* @param options - Additional options for creating the session.
441
* @returns A promise that resolves to an authentication session.
442
*/
443
createSession(scopes: string[], options: IAuthenticationProviderSessionOptions): Promise<AuthenticationSession>;
444
445
/**
446
* Get existing sessions that match the given authentication constraints.
447
*
448
* @param constraint The authentication constraint containing challenges and optional scopes
449
* @param options Options for the session request
450
* @returns A thenable that resolves to an array of existing authentication sessions
451
*/
452
getSessionsFromChallenges?(constraint: IAuthenticationConstraint, options: IAuthenticationProviderSessionOptions): Promise<readonly AuthenticationSession[]>;
453
454
/**
455
* Create a new session based on authentication constraints.
456
* This is called when no existing session matches the constraint requirements.
457
*
458
* @param constraint The authentication constraint containing challenges and optional scopes
459
* @param options Options for the session creation
460
* @returns A thenable that resolves to a new authentication session
461
*/
462
createSessionFromChallenges?(constraint: IAuthenticationConstraint, options: IAuthenticationProviderSessionOptions): Promise<AuthenticationSession>;
463
464
/**
465
* Removes the session corresponding to the specified session ID.
466
* If the removal is successful, the `onDidChangeSessions` event should be fired.
467
* If a session cannot be removed, the provider should reject with an error message.
468
* @param sessionId - The ID of the session to remove.
469
*/
470
removeSession(sessionId: string): Promise<void>;
471
}
472
473