Path: blob/main/src/vs/workbench/services/authentication/common/authentication.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/4import { Event } from '../../../../base/common/event.js';5import { IDisposable } from '../../../../base/common/lifecycle.js';6import { IAuthenticationChallenge, IAuthorizationProtectedResourceMetadata, IAuthorizationServerMetadata } from '../../../../base/common/oauth.js';7import { URI } from '../../../../base/common/uri.js';8import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';910/**11* Use this if you don't want the onDidChangeSessions event to fire in the extension host12*/13export const INTERNAL_AUTH_PROVIDER_PREFIX = '__';1415export interface AuthenticationSessionAccount {16label: string;17id: string;18}1920export interface AuthenticationSession {21id: string;22accessToken: string;23account: AuthenticationSessionAccount;24scopes: ReadonlyArray<string>;25idToken?: string;26}2728export interface AuthenticationSessionsChangeEvent {29added: ReadonlyArray<AuthenticationSession> | undefined;30removed: ReadonlyArray<AuthenticationSession> | undefined;31changed: ReadonlyArray<AuthenticationSession> | undefined;32}3334export interface AuthenticationProviderInformation {35id: string;36label: string;37authorizationServerGlobs?: ReadonlyArray<string>;38}3940/**41* Options for creating an authentication session via the service.42*/43export interface IAuthenticationCreateSessionOptions {44activateImmediate?: boolean;45/**46* The account that is being asked about. If this is passed in, the provider should47* attempt to return the sessions that are only related to this account.48*/49account?: AuthenticationSessionAccount;50/**51* The authorization server URI to use for this creation request. If passed in, first we validate that52* the provider can use this authorization server, then it is passed down to the auth provider.53*/54authorizationServer?: URI;55/**56* Allows the authentication provider to take in additional parameters.57* It is up to the provider to define what these parameters are and handle them.58* This is useful for passing in additional information that is specific to the provider59* and not part of the standard authentication flow.60*/61[key: string]: any;62}6364export interface IAuthenticationWWWAuthenticateRequest {65/**66* The raw WWW-Authenticate header value that triggered this challenge.67* This will be parsed by the authentication provider to extract the necessary68* challenge information.69*/70readonly wwwAuthenticate: string;7172/**73* Optional scopes for the session. If not provided, the authentication provider74* may use default scopes or extract them from the challenge.75*/76readonly scopes?: readonly string[];77}7879export function isAuthenticationWWWAuthenticateRequest(obj: unknown): obj is IAuthenticationWWWAuthenticateRequest {80return typeof obj === 'object'81&& obj !== null82&& 'wwwAuthenticate' in obj83&& (typeof obj.wwwAuthenticate === 'string');84}8586/**87* Represents constraints for authentication, including challenges and optional scopes.88* This is used when creating or retrieving sessions that must satisfy specific authentication89* requirements from WWW-Authenticate headers.90*/91export interface IAuthenticationConstraint {92/**93* Array of authentication challenges parsed from WWW-Authenticate headers.94*/95readonly challenges: readonly IAuthenticationChallenge[];9697/**98* Optional scopes for the session. If not provided, the authentication provider99* may extract scopes from the challenges or use default scopes.100*/101readonly scopes?: readonly string[];102}103104/**105* Options for getting authentication sessions via the service.106*/107export interface IAuthenticationGetSessionsOptions {108/**109* The account that is being asked about. If this is passed in, the provider should110* attempt to return the sessions that are only related to this account.111*/112account?: AuthenticationSessionAccount;113/**114* The authorization server URI to use for this request. If passed in, first we validate that115* the provider can use this authorization server, then it is passed down to the auth provider.116*/117authorizationServer?: URI;118/**119* Allows the authentication provider to take in additional parameters.120* It is up to the provider to define what these parameters are and handle them.121* This is useful for passing in additional information that is specific to the provider122* and not part of the standard authentication flow.123*/124[key: string]: any;125}126127export interface AllowedExtension {128id: string;129name: string;130/**131* If true or undefined, the extension is allowed to use the account132* If false, the extension is not allowed to use the account133* TODO: undefined shouldn't be a valid value, but it is for now134*/135allowed?: boolean;136lastUsed?: number;137// If true, this comes from the product.json138trusted?: boolean;139}140141export interface IAuthenticationProviderHostDelegate {142/** Priority for this delegate, delegates are tested in descending priority order */143readonly priority: number;144create(authorizationServer: URI, serverMetadata: IAuthorizationServerMetadata, resource: IAuthorizationProtectedResourceMetadata | undefined): Promise<string>;145}146147export const IAuthenticationService = createDecorator<IAuthenticationService>('IAuthenticationService');148149export interface IAuthenticationService {150readonly _serviceBrand: undefined;151152/**153* Fires when an authentication provider has been registered154*/155readonly onDidRegisterAuthenticationProvider: Event<AuthenticationProviderInformation>;156/**157* Fires when an authentication provider has been unregistered158*/159readonly onDidUnregisterAuthenticationProvider: Event<AuthenticationProviderInformation>;160161/**162* Fires when the list of sessions for a provider has been added, removed or changed163*/164readonly onDidChangeSessions: Event<{ providerId: string; label: string; event: AuthenticationSessionsChangeEvent }>;165166/**167* Fires when the list of declaredProviders has changed168*/169readonly onDidChangeDeclaredProviders: Event<void>;170171/**172* All providers that have been statically declared by extensions. These may not actually be registered or active yet.173*/174readonly declaredProviders: AuthenticationProviderInformation[];175176/**177* Registers that an extension has declared an authentication provider in their package.json178* @param provider The provider information to register179*/180registerDeclaredAuthenticationProvider(provider: AuthenticationProviderInformation): void;181182/**183* Unregisters a declared authentication provider184* @param id The id of the provider to unregister185*/186unregisterDeclaredAuthenticationProvider(id: string): void;187188/**189* Checks if an authentication provider has been registered190* @param id The id of the provider to check191*/192isAuthenticationProviderRegistered(id: string): boolean;193194/**195* Checks if an authentication provider is dynamic196* @param id The id of the provider to check197*/198isDynamicAuthenticationProvider(id: string): boolean;199200/**201* Registers an authentication provider202* @param id The id of the provider203* @param provider The implementation of the provider204*/205registerAuthenticationProvider(id: string, provider: IAuthenticationProvider): void;206207/**208* Unregisters an authentication provider209* @param id The id of the provider to unregister210*/211unregisterAuthenticationProvider(id: string): void;212213/**214* Gets the provider ids of all registered authentication providers215*/216getProviderIds(): string[];217218/**219* Gets the provider with the given id.220* @param id The id of the provider to get221* @throws if the provider is not registered222*/223getProvider(id: string): IAuthenticationProvider;224225/**226* Gets all accounts that are currently logged in across all sessions227* @param id The id of the provider to ask for accounts228* @returns A promise that resolves to an array of accounts229*/230getAccounts(id: string): Promise<ReadonlyArray<AuthenticationSessionAccount>>;231232/**233* Gets all sessions that satisfy the given scopes from the provider with the given id234* @param id The id of the provider to ask for a session235* @param scopes The scopes for the session236* @param options Additional options for getting sessions237* @param activateImmediate If true, the provider should activate immediately if it is not already238*/239getSessions(id: string, scopeListOrRequest?: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate?: boolean): Promise<ReadonlyArray<AuthenticationSession>>;240241/**242* Creates an AuthenticationSession with the given provider and scopes243* @param providerId The id of the provider244* @param scopes The scopes to request245* @param options Additional options for creating the session246*/247createSession(providerId: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise<AuthenticationSession>;248249/**250* Removes the session with the given id from the provider with the given id251* @param providerId The id of the provider252* @param sessionId The id of the session to remove253*/254removeSession(providerId: string, sessionId: string): Promise<void>;255256/**257* Gets a provider id for a specified authorization server258* @param authorizationServer The authorization server url that this provider is responsible for259*/260getOrActivateProviderIdForServer(authorizationServer: URI): Promise<string | undefined>;261262/**263* Allows the ability register a delegate that will be used to start authentication providers264* @param delegate The delegate to register265*/266registerAuthenticationProviderHostDelegate(delegate: IAuthenticationProviderHostDelegate): IDisposable;267268/**269* Creates a dynamic authentication provider for the given server metadata270* @param serverMetadata The metadata for the server that is being authenticated against271*/272createDynamicAuthenticationProvider(authorizationServer: URI, serverMetadata: IAuthorizationServerMetadata, resourceMetadata: IAuthorizationProtectedResourceMetadata | undefined): Promise<IAuthenticationProvider | undefined>;273}274275export function isAuthenticationSession(thing: unknown): thing is AuthenticationSession {276if (typeof thing !== 'object' || !thing) {277return false;278}279const maybe = thing as AuthenticationSession;280if (typeof maybe.id !== 'string') {281return false;282}283if (typeof maybe.accessToken !== 'string') {284return false;285}286if (typeof maybe.account !== 'object' || !maybe.account) {287return false;288}289if (typeof maybe.account.label !== 'string') {290return false;291}292if (typeof maybe.account.id !== 'string') {293return false;294}295if (!Array.isArray(maybe.scopes)) {296return false;297}298if (maybe.idToken && typeof maybe.idToken !== 'string') {299return false;300}301return true;302}303304// TODO: Move this into MainThreadAuthentication305export const IAuthenticationExtensionsService = createDecorator<IAuthenticationExtensionsService>('IAuthenticationExtensionsService');306export interface IAuthenticationExtensionsService {307readonly _serviceBrand: undefined;308309/**310* Fires when an account preference for a specific provider has changed for the specified extensions. Does not fire when:311* * An account preference is removed312* * A session preference is changed (because it's deprecated)313* * A session preference is removed (because it's deprecated)314*/315onDidChangeAccountPreference: Event<{ extensionIds: string[]; providerId: string }>;316/**317* Returns the accountName (also known as account.label) to pair with `IAuthenticationAccessService` to get the account preference318* @param providerId The authentication provider id319* @param extensionId The extension id to get the preference for320* @returns The accountName of the preference, or undefined if there is no preference set321*/322getAccountPreference(extensionId: string, providerId: string): string | undefined;323/**324* Sets the account preference for the given provider and extension325* @param providerId The authentication provider id326* @param extensionId The extension id to set the preference for327* @param account The account to set the preference to328*/329updateAccountPreference(extensionId: string, providerId: string, account: AuthenticationSessionAccount): void;330/**331* Removes the account preference for the given provider and extension332* @param providerId The authentication provider id333* @param extensionId The extension id to remove the preference for334*/335removeAccountPreference(extensionId: string, providerId: string): void;336/**337* @deprecated Sets the session preference for the given provider and extension338* @param providerId339* @param extensionId340* @param session341*/342updateSessionPreference(providerId: string, extensionId: string, session: AuthenticationSession): void;343/**344* @deprecated Gets the session preference for the given provider and extension345* @param providerId346* @param extensionId347* @param scopes348*/349getSessionPreference(providerId: string, extensionId: string, scopes: string[]): string | undefined;350/**351* @deprecated Removes the session preference for the given provider and extension352* @param providerId353* @param extensionId354* @param scopes355*/356removeSessionPreference(providerId: string, extensionId: string, scopes: string[]): void;357selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): Promise<AuthenticationSession>;358requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): void;359requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray<string> | IAuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string): Promise<void>;360updateNewSessionRequests(providerId: string, addedSessions: readonly AuthenticationSession[]): void;361}362363/**364* Options passed to the authentication provider when asking for sessions.365*/366export interface IAuthenticationProviderSessionOptions {367/**368* The account that is being asked about. If this is passed in, the provider should369* attempt to return the sessions that are only related to this account.370*/371account?: AuthenticationSessionAccount;372/**373* The authorization server that is being asked about. If this is passed in, the provider should374* attempt to return sessions that are only related to this authorization server.375*/376authorizationServer?: URI;377/**378* Allows the authentication provider to take in additional parameters.379* It is up to the provider to define what these parameters are and handle them.380* This is useful for passing in additional information that is specific to the provider381* and not part of the standard authentication flow.382*/383[key: string]: any;384}385386/**387* Represents an authentication provider.388*/389export interface IAuthenticationProvider {390/**391* The unique identifier of the authentication provider.392*/393readonly id: string;394395/**396* The display label of the authentication provider.397*/398readonly label: string;399400/**401* The resolved authorization servers. These can still contain globs, but should be concrete URIs402*/403readonly authorizationServers?: ReadonlyArray<URI>;404405/**406* Indicates whether the authentication provider supports multiple accounts.407*/408readonly supportsMultipleAccounts: boolean;409410/**411* Optional function to provide a custom confirmation message for authentication prompts.412* If not implemented, the default confirmation messages will be used.413* @param extensionName - The name of the extension requesting authentication.414* @param recreatingSession - Whether this is recreating an existing session.415* @returns A custom confirmation message or undefined to use the default message.416*/417readonly confirmation?: (extensionName: string, recreatingSession: boolean) => string | undefined;418419/**420* An {@link Event} which fires when the array of sessions has changed, or data421* within a session has changed.422*/423readonly onDidChangeSessions: Event<AuthenticationSessionsChangeEvent>;424425/**426* Retrieves a list of authentication sessions.427* @param scopes - An optional list of scopes. If provided, the sessions returned should match these permissions, otherwise all sessions should be returned.428* @param options - Additional options for getting sessions.429* @returns A promise that resolves to an array of authentication sessions.430*/431getSessions(scopes: string[] | undefined, options: IAuthenticationProviderSessionOptions): Promise<readonly AuthenticationSession[]>;432433/**434* Prompts the user to log in.435* If login is successful, the `onDidChangeSessions` event should be fired.436* If login fails, a rejected promise should be returned.437* 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.438* @param scopes - A list of scopes that the new session should be created with.439* @param options - Additional options for creating the session.440* @returns A promise that resolves to an authentication session.441*/442createSession(scopes: string[], options: IAuthenticationProviderSessionOptions): Promise<AuthenticationSession>;443444/**445* Get existing sessions that match the given authentication constraints.446*447* @param constraint The authentication constraint containing challenges and optional scopes448* @param options Options for the session request449* @returns A thenable that resolves to an array of existing authentication sessions450*/451getSessionsFromChallenges?(constraint: IAuthenticationConstraint, options: IAuthenticationProviderSessionOptions): Promise<readonly AuthenticationSession[]>;452453/**454* Create a new session based on authentication constraints.455* This is called when no existing session matches the constraint requirements.456*457* @param constraint The authentication constraint containing challenges and optional scopes458* @param options Options for the session creation459* @returns A thenable that resolves to a new authentication session460*/461createSessionFromChallenges?(constraint: IAuthenticationConstraint, options: IAuthenticationProviderSessionOptions): Promise<AuthenticationSession>;462463/**464* Removes the session corresponding to the specified session ID.465* If the removal is successful, the `onDidChangeSessions` event should be fired.466* If a session cannot be removed, the provider should reject with an error message.467* @param sessionId - The ID of the session to remove.468*/469removeSession(sessionId: string): Promise<void>;470}471472473