diff --git a/extensions/microsoft-authentication/src/node/authProvider.ts b/extensions/microsoft-authentication/src/node/authProvider.ts index bccfcc2e9e4..c2145f75bcf 100644 --- a/extensions/microsoft-authentication/src/node/authProvider.ts +++ b/extensions/microsoft-authentication/src/node/authProvider.ts @@ -290,8 +290,11 @@ export class MsalAuthProvider implements AuthenticationProvider { async getSessionsFromChallenges(constraint: AuthenticationConstraint, options: AuthenticationProviderSessionOptions): Promise { this._logger.info('[getSessionsFromChallenges]', 'starting with', constraint.challenges.length, 'challenges'); - // Use scopes from constraint if provided, otherwise extract from challenges - const scopes = constraint.scopes?.length ? [...constraint.scopes] : this.extractScopesFromChallenges(constraint.challenges); + // Use scopes from challenges if provided, otherwise use fallback scopes + const scopes = this.extractScopesFromChallenges(constraint.challenges) ?? constraint.fallbackScopes; + if (!scopes || scopes.length === 0) { + throw new Error('No scopes found in authentication challenges or fallback scopes'); + } const claims = this.extractClaimsFromChallenges(constraint.challenges); if (!claims) { throw new Error('No claims found in authentication challenges'); @@ -309,8 +312,11 @@ export class MsalAuthProvider implements AuthenticationProvider { async createSessionFromChallenges(constraint: AuthenticationConstraint, options: AuthenticationProviderSessionOptions): Promise { this._logger.info('[createSessionFromChallenges]', 'starting with', constraint.challenges.length, 'challenges'); - // Use scopes from constraint if provided, otherwise extract from challenges - const scopes = constraint.scopes?.length ? [...constraint.scopes] : this.extractScopesFromChallenges(constraint.challenges); + // Use scopes from challenges if provided, otherwise use fallback scopes + const scopes = this.extractScopesFromChallenges(constraint.challenges) ?? constraint.fallbackScopes; + if (!scopes || scopes.length === 0) { + throw new Error('No scopes found in authentication challenges or fallback scopes'); + } const claims = this.extractClaimsFromChallenges(constraint.challenges); // Use scopes if available, otherwise fall back to default scopes @@ -392,14 +398,13 @@ export class MsalAuthProvider implements AuthenticationProvider { throw lastError ?? new Error('No auth flow succeeded'); } - private extractScopesFromChallenges(challenges: readonly AuthenticationChallenge[]): string[] { - const scopes: string[] = []; + private extractScopesFromChallenges(challenges: readonly AuthenticationChallenge[]): string[] | undefined { for (const challenge of challenges) { if (challenge.scheme.toLowerCase() === 'bearer' && challenge.params.scope) { - scopes.push(...challenge.params.scope.split(' ')); + return challenge.params.scope.split(' '); } } - return scopes; + return undefined; } private extractClaimsFromChallenges(challenges: readonly AuthenticationChallenge[]): string | undefined { diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 902230bc7cd..ff002feb111 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -6,8 +6,8 @@ import { Disposable, DisposableMap } from '../../../base/common/lifecycle.js'; import * as nls from '../../../nls.js'; import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js'; -import { AuthenticationSession, AuthenticationSessionsChangeEvent, IAuthenticationProvider, IAuthenticationService, IAuthenticationExtensionsService, AuthenticationSessionAccount, IAuthenticationProviderSessionOptions, isAuthenticationWWWAuthenticateRequest, IAuthenticationConstraint } from '../../services/authentication/common/authentication.js'; -import { AuthenticationWWWAuthenticateRequest, ExtHostAuthenticationShape, ExtHostContext, MainContext, MainThreadAuthenticationShape } from '../common/extHost.protocol.js'; +import { AuthenticationSession, AuthenticationSessionsChangeEvent, IAuthenticationProvider, IAuthenticationService, IAuthenticationExtensionsService, AuthenticationSessionAccount, IAuthenticationProviderSessionOptions, isAuthenticationWwwAuthenticateRequest, IAuthenticationConstraint, IAuthenticationWwwAuthenticateRequest } from '../../services/authentication/common/authentication.js'; +import { ExtHostAuthenticationShape, ExtHostContext, MainContext, MainThreadAuthenticationShape } from '../common/extHost.protocol.js'; import { IDialogService, IPromptButton } from '../../../platform/dialogs/common/dialogs.js'; import Severity from '../../../base/common/severity.js'; import { INotificationService } from '../../../platform/notification/common/notification.js'; @@ -345,7 +345,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu return result.result === chosenAccountLabel; } - private async doGetSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise { + private async doGetSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise { const authorizationServer = URI.revive(options.authorizationServer); const sessions = await this.authenticationService.getSessions(providerId, scopeListOrRequest, { account: options.account, authorizationServer }, true); const provider = this.authenticationService.getProvider(providerId); @@ -452,8 +452,8 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu return undefined; } - async $getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise { - const scopes = isAuthenticationWWWAuthenticateRequest(scopeListOrRequest) ? scopeListOrRequest.scopes : scopeListOrRequest; + async $getSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise { + const scopes = isAuthenticationWwwAuthenticateRequest(scopeListOrRequest) ? scopeListOrRequest.fallbackScopes : scopeListOrRequest; if (scopes) { this.sendClientIdUsageTelemetry(extensionId, providerId, scopes); } @@ -461,8 +461,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu if (session) { this.sendProviderUsageTelemetry(extensionId, providerId); - const scopes = isAuthenticationWWWAuthenticateRequest(scopeListOrRequest) ? scopeListOrRequest.scopes : scopeListOrRequest; - this.authenticationUsageService.addAccountUsage(providerId, session.account.label, scopes, extensionId, extensionName); + this.authenticationUsageService.addAccountUsage(providerId, session.account.label, session.scopes, extensionId, extensionName); } return session; diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 0bb808d594a..9afd4467b0e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -301,7 +301,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I })(); const authentication: typeof vscode.authentication = { - getSession(providerId: string, scopesOrChallenge: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options?: vscode.AuthenticationGetSessionOptions) { + getSession(providerId: string, scopesOrChallenge: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options?: vscode.AuthenticationGetSessionOptions) { if (!Array.isArray(scopesOrChallenge)) { checkProposedApiEnabled(extension, 'authenticationChallenges'); } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index fdd9a91daca..88ea921a3fa 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -80,7 +80,7 @@ import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescrip import { TypeHierarchyItem } from '../../contrib/typeHierarchy/common/typeHierarchy.js'; import { RelatedInformationResult, RelatedInformationType } from '../../services/aiRelatedInformation/common/aiRelatedInformation.js'; import { AiSettingsSearchProviderOptions, AiSettingsSearchResult } from '../../services/aiSettingsSearch/common/aiSettingsSearch.js'; -import { AuthenticationSession, AuthenticationSessionAccount, AuthenticationSessionsChangeEvent, IAuthenticationCreateSessionOptions, IAuthenticationGetSessionsOptions } from '../../services/authentication/common/authentication.js'; +import { AuthenticationSession, AuthenticationSessionAccount, AuthenticationSessionsChangeEvent, IAuthenticationConstraint, IAuthenticationCreateSessionOptions, IAuthenticationGetSessionsOptions, IAuthenticationWwwAuthenticateRequest } from '../../services/authentication/common/authentication.js'; import { EditorGroupColumn } from '../../services/editor/common/editorGroupColumn.js'; import { IExtensionDescriptionDelta, IStaticWorkspaceData } from '../../services/extensions/common/extensionHostProtocol.js'; import { IResolveAuthorityResult } from '../../services/extensions/common/extensionHostProxy.js'; @@ -186,27 +186,11 @@ export interface AuthenticationGetSessionOptions { account?: AuthenticationSessionAccount; } -export interface AuthenticationChallenge { - scheme: string; - params: Record; -} - -export interface AuthenticationWWWAuthenticateRequest { - wwwAuthenticate: string; - scopes?: readonly string[]; -} - -//TODO: I don't love the name of this interface... -export interface AuthenticationConstraint { - challenges: readonly AuthenticationChallenge[]; - scopes?: readonly string[]; -} - export interface MainThreadAuthenticationShape extends IDisposable { $registerAuthenticationProvider(id: string, label: string, supportsMultipleAccounts: boolean, supportedAuthorizationServers?: UriComponents[], supportsChallenges?: boolean): Promise; $unregisterAuthenticationProvider(id: string): Promise; $sendDidChangeSessions(providerId: string, event: AuthenticationSessionsChangeEvent): Promise; - $getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise; + $getSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, extensionId: string, extensionName: string, options: AuthenticationGetSessionOptions): Promise; $getAccounts(providerId: string): Promise>; $removeSession(providerId: string, sessionId: string): Promise; $waitForUriHandler(expectedUri: UriComponents): Promise; @@ -2007,8 +1991,8 @@ export interface ExtHostLabelServiceShape { export interface ExtHostAuthenticationShape { $getSessions(id: string, scopes: string[] | undefined, options: IAuthenticationGetSessionsOptions): Promise>; $createSession(id: string, scopes: string[], options: IAuthenticationCreateSessionOptions): Promise; - $getSessionsFromChallenges(id: string, constraint: AuthenticationConstraint, options: IAuthenticationGetSessionsOptions): Promise>; - $createSessionFromChallenges(id: string, constraint: AuthenticationConstraint, options: IAuthenticationCreateSessionOptions): Promise; + $getSessionsFromChallenges(id: string, constraint: IAuthenticationConstraint, options: IAuthenticationGetSessionsOptions): Promise>; + $createSessionFromChallenges(id: string, constraint: IAuthenticationConstraint, options: IAuthenticationCreateSessionOptions): Promise; $removeSession(id: string, sessionId: string): Promise; $onDidChangeAuthenticationSessions(id: string, label: string, extensionIdFilter?: string[]): Promise; $onDidUnregisterAuthenticationProvider(id: string): Promise; diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 7fe640404ce..c3b5bf35bc2 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -9,7 +9,7 @@ import { Emitter, Event } from '../../../base/common/event.js'; import { MainContext, MainThreadAuthenticationShape, ExtHostAuthenticationShape } from './extHost.protocol.js'; import { Disposable, ProgressLocation } from './extHostTypes.js'; import { IExtensionDescription, ExtensionIdentifier } from '../../../platform/extensions/common/extensions.js'; -import { INTERNAL_AUTH_PROVIDER_PREFIX, isAuthenticationWWWAuthenticateRequest } from '../../services/authentication/common/authentication.js'; +import { INTERNAL_AUTH_PROVIDER_PREFIX, isAuthenticationWwwAuthenticateRequest } from '../../services/authentication/common/authentication.js'; import { createDecorator } from '../../../platform/instantiation/common/instantiation.js'; import { IExtHostRpcService } from './extHostRpcService.js'; import { URI, UriComponents } from '../../../base/common/uri.js'; @@ -79,32 +79,32 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { ); } - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: vscode.AuthenticationForceNewSessionOptions })): Promise; - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & { forceNewSession: true }): Promise; - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & { forceNewSession: vscode.AuthenticationForceNewSessionOptions }): Promise; - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions): Promise; - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWWWAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions = {}): Promise { + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: vscode.AuthenticationForceNewSessionOptions })): Promise; + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & { forceNewSession: true }): Promise; + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions & { forceNewSession: vscode.AuthenticationForceNewSessionOptions }): Promise; + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions): Promise; + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopesOrRequest: readonly string[] | vscode.AuthenticationWwwAuthenticateRequest, options: vscode.AuthenticationGetSessionOptions = {}): Promise { const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); const keys: (keyof vscode.AuthenticationGetSessionOptions)[] = Object.keys(options) as (keyof vscode.AuthenticationGetSessionOptions)[]; const optionsStr = keys.sort().map(key => `${key}:${!!options[key]}`).join(', '); // old shape, remove next milestone if ( - 'challenge' in scopesOrRequest - && typeof scopesOrRequest.challenge === 'string' - && !scopesOrRequest.wwwAuthenticate + 'scopes' in scopesOrRequest + && typeof scopesOrRequest.scopes === 'string' + && !scopesOrRequest.fallbackScopes ) { scopesOrRequest = { - wwwAuthenticate: scopesOrRequest.challenge, - scopes: scopesOrRequest.scopes + wwwAuthenticate: scopesOrRequest.wwwAuthenticate, + fallbackScopes: scopesOrRequest.scopes }; } let singlerKey: string; - if (isAuthenticationWWWAuthenticateRequest(scopesOrRequest)) { - const challenge = scopesOrRequest as vscode.AuthenticationWWWAuthenticateRequest; + if (isAuthenticationWwwAuthenticateRequest(scopesOrRequest)) { + const challenge = scopesOrRequest as vscode.AuthenticationWwwAuthenticateRequest; const challengeStr = challenge.wwwAuthenticate; - const scopesStr = challenge.scopes ? [...challenge.scopes].sort().join(' ') : ''; + const scopesStr = challenge.fallbackScopes ? [...challenge.fallbackScopes].sort().join(' ') : ''; singlerKey = `${extensionId} ${providerId} challenge:${challengeStr} ${scopesStr} ${optionsStr}`; } else { const sortedScopes = [...scopesOrRequest].sort().join(' '); diff --git a/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts b/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts index d208a21c7cd..ef2e32e2e15 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationExtensionsService.ts @@ -16,7 +16,7 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo import { IActivityService, NumberBadge } from '../../activity/common/activity.js'; import { IAuthenticationAccessService } from './authenticationAccessService.js'; import { IAuthenticationUsageService } from './authenticationUsageService.js'; -import { AuthenticationSession, IAuthenticationProvider, IAuthenticationService, IAuthenticationExtensionsService, AuthenticationSessionAccount, IAuthenticationWWWAuthenticateRequest, isAuthenticationWWWAuthenticateRequest } from '../common/authentication.js'; +import { AuthenticationSession, IAuthenticationProvider, IAuthenticationService, IAuthenticationExtensionsService, AuthenticationSessionAccount, IAuthenticationWwwAuthenticateRequest, isAuthenticationWwwAuthenticateRequest } from '../common/authentication.js'; import { Emitter } from '../../../../base/common/event.js'; import { IProductService } from '../../../../platform/product/common/productService.js'; import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js'; @@ -287,7 +287,7 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth /** * This function should be used only when there are sessions to disambiguate. */ - async selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, availableSessions: AuthenticationSession[]): Promise { + async selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, availableSessions: AuthenticationSession[]): Promise { const allAccounts = await this._authenticationService.getAccounts(providerId); if (!allAccounts.length) { throw new Error('No accounts available'); @@ -359,7 +359,7 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth }); } - private async completeSessionAccessRequest(provider: IAuthenticationProvider, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest): Promise { + private async completeSessionAccessRequest(provider: IAuthenticationProvider, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest): Promise { const providerRequests = this._sessionAccessRequestItems.get(provider.id) || {}; const existingRequest = providerRequests[extensionId]; if (!existingRequest) { @@ -390,7 +390,7 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth } } - requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, possibleSessions: AuthenticationSession[]): void { + requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, possibleSessions: AuthenticationSession[]): void { const providerRequests = this._sessionAccessRequestItems.get(providerId) || {}; const hasExistingRequest = providerRequests[extensionId]; if (hasExistingRequest) { @@ -424,7 +424,7 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth this.updateBadgeCount(); } - async requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string): Promise { + async requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, extensionId: string, extensionName: string): Promise { if (!this._authenticationService.isAuthenticationProviderRegistered(providerId)) { // Activate has already been called for the authentication provider, but it cannot block on registering itself // since this is sync and returns a disposable. So, wait for registration event to fire that indicates the @@ -447,8 +447,8 @@ export class AuthenticationExtensionsService extends Disposable implements IAuth } const providerRequests = this._signInRequestItems.get(providerId); - const signInRequestKey = isAuthenticationWWWAuthenticateRequest(scopeListOrRequest) - ? `${scopeListOrRequest.wwwAuthenticate}:${scopeListOrRequest.scopes?.join(SCOPESLIST_SEPARATOR) ?? ''}` + const signInRequestKey = isAuthenticationWwwAuthenticateRequest(scopeListOrRequest) + ? `${scopeListOrRequest.wwwAuthenticate}:${scopeListOrRequest.fallbackScopes?.join(SCOPESLIST_SEPARATOR) ?? ''}` : `${scopeListOrRequest.join(SCOPESLIST_SEPARATOR)}`; const extensionHasExistingRequest = providerRequests && providerRequests[signInRequestKey] diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index 1e351606021..0eaf7b78dd3 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -12,7 +12,7 @@ import { InstantiationType, registerSingleton } from '../../../../platform/insta import { IProductService } from '../../../../platform/product/common/productService.js'; import { ISecretStorageService } from '../../../../platform/secrets/common/secrets.js'; import { IAuthenticationAccessService } from './authenticationAccessService.js'; -import { AuthenticationProviderInformation, AuthenticationSession, AuthenticationSessionAccount, AuthenticationSessionsChangeEvent, IAuthenticationCreateSessionOptions, IAuthenticationGetSessionsOptions, IAuthenticationProvider, IAuthenticationProviderHostDelegate, IAuthenticationService, IAuthenticationWWWAuthenticateRequest, isAuthenticationWWWAuthenticateRequest } from '../common/authentication.js'; +import { AuthenticationProviderInformation, AuthenticationSession, AuthenticationSessionAccount, AuthenticationSessionsChangeEvent, IAuthenticationCreateSessionOptions, IAuthenticationGetSessionsOptions, IAuthenticationProvider, IAuthenticationProviderHostDelegate, IAuthenticationService, IAuthenticationWwwAuthenticateRequest, isAuthenticationWwwAuthenticateRequest } from '../common/authentication.js'; import { IBrowserWorkbenchEnvironmentService } from '../../environment/browser/environmentService.js'; import { ActivationKind, IExtensionService } from '../../extensions/common/extensions.js'; import { ILogService } from '../../../../platform/log/common/log.js'; @@ -276,7 +276,7 @@ export class AuthenticationService extends Disposable implements IAuthentication return accounts; } - async getSessions(id: string, scopeListOrRequest?: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate: boolean = false): Promise> { + async getSessions(id: string, scopeListOrRequest?: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate: boolean = false): Promise> { if (this._disposedSource.token.isCancellationRequested) { return []; } @@ -291,12 +291,12 @@ export class AuthenticationService extends Disposable implements IAuthentication throw new Error(`The authorization server '${authServerStr}' is not supported by the authentication provider '${id}'.`); } } - if (isAuthenticationWWWAuthenticateRequest(scopeListOrRequest)) { + if (isAuthenticationWwwAuthenticateRequest(scopeListOrRequest)) { if (!authProvider.getSessionsFromChallenges) { throw new Error(`The authentication provider '${id}' does not support getting sessions from challenges.`); } return await authProvider.getSessionsFromChallenges( - { challenges: parseWWWAuthenticateHeader(scopeListOrRequest.wwwAuthenticate), scopes: scopeListOrRequest.scopes }, + { challenges: parseWWWAuthenticateHeader(scopeListOrRequest.wwwAuthenticate), fallbackScopes: scopeListOrRequest.fallbackScopes }, { ...options } ); } @@ -306,19 +306,19 @@ export class AuthenticationService extends Disposable implements IAuthentication } } - async createSession(id: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise { + async createSession(id: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise { if (this._disposedSource.token.isCancellationRequested) { throw new Error('Authentication service is disposed.'); } const authProvider = this._authenticationProviders.get(id) || await this.tryActivateProvider(id, !!options?.activateImmediate); if (authProvider) { - if (isAuthenticationWWWAuthenticateRequest(scopeListOrRequest)) { + if (isAuthenticationWwwAuthenticateRequest(scopeListOrRequest)) { if (!authProvider.createSessionFromChallenges) { throw new Error(`The authentication provider '${id}' does not support creating sessions from challenges.`); } return await authProvider.createSessionFromChallenges( - { challenges: parseWWWAuthenticateHeader(scopeListOrRequest.wwwAuthenticate), scopes: scopeListOrRequest.scopes }, + { challenges: parseWWWAuthenticateHeader(scopeListOrRequest.wwwAuthenticate), fallbackScopes: scopeListOrRequest.fallbackScopes }, { ...options } ); } diff --git a/src/vs/workbench/services/authentication/common/authentication.ts b/src/vs/workbench/services/authentication/common/authentication.ts index 46f2a1ba752..2a60f4fecb9 100644 --- a/src/vs/workbench/services/authentication/common/authentication.ts +++ b/src/vs/workbench/services/authentication/common/authentication.ts @@ -62,7 +62,7 @@ export interface IAuthenticationCreateSessionOptions { [key: string]: any; } -export interface IAuthenticationWWWAuthenticateRequest { +export interface IAuthenticationWwwAuthenticateRequest { /** * The raw WWW-Authenticate header value that triggered this challenge. * This will be parsed by the authentication provider to extract the necessary @@ -74,10 +74,10 @@ export interface IAuthenticationWWWAuthenticateRequest { * Optional scopes for the session. If not provided, the authentication provider * may use default scopes or extract them from the challenge. */ - readonly scopes?: readonly string[]; + readonly fallbackScopes?: readonly string[]; } -export function isAuthenticationWWWAuthenticateRequest(obj: unknown): obj is IAuthenticationWWWAuthenticateRequest { +export function isAuthenticationWwwAuthenticateRequest(obj: unknown): obj is IAuthenticationWwwAuthenticateRequest { return typeof obj === 'object' && obj !== null && 'wwwAuthenticate' in obj @@ -99,7 +99,7 @@ export interface IAuthenticationConstraint { * Optional scopes for the session. If not provided, the authentication provider * may extract scopes from the challenges or use default scopes. */ - readonly scopes?: readonly string[]; + readonly fallbackScopes?: readonly string[]; } /** @@ -237,7 +237,7 @@ export interface IAuthenticationService { * @param options Additional options for getting sessions * @param activateImmediate If true, the provider should activate immediately if it is not already */ - getSessions(id: string, scopeListOrRequest?: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate?: boolean): Promise>; + getSessions(id: string, scopeListOrRequest?: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, options?: IAuthenticationGetSessionsOptions, activateImmediate?: boolean): Promise>; /** * Creates an AuthenticationSession with the given provider and scopes @@ -245,7 +245,7 @@ export interface IAuthenticationService { * @param scopes The scopes to request * @param options Additional options for creating the session */ - createSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise; + createSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, options?: IAuthenticationCreateSessionOptions): Promise; /** * Removes the session with the given id from the provider with the given id @@ -355,9 +355,9 @@ export interface IAuthenticationExtensionsService { * @param scopes */ removeSessionPreference(providerId: string, extensionId: string, scopes: string[]): void; - selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): Promise; - requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): void; - requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWWWAuthenticateRequest, extensionId: string, extensionName: string): Promise; + selectSession(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): Promise; + requestSessionAccess(providerId: string, extensionId: string, extensionName: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, possibleSessions: readonly AuthenticationSession[]): void; + requestNewSession(providerId: string, scopeListOrRequest: ReadonlyArray | IAuthenticationWwwAuthenticateRequest, extensionId: string, extensionName: string): Promise; updateNewSessionRequests(providerId: string, addedSessions: readonly AuthenticationSession[]): void; } diff --git a/src/vscode-dts/vscode.proposed.authenticationChallenges.d.ts b/src/vscode-dts/vscode.proposed.authenticationChallenges.d.ts index 2550d66c24e..3cc2d5b7696 100644 --- a/src/vscode-dts/vscode.proposed.authenticationChallenges.d.ts +++ b/src/vscode-dts/vscode.proposed.authenticationChallenges.d.ts @@ -21,7 +21,7 @@ declare module 'vscode' { * the challenges in this WWW-Authenticate value. * @note For more information on WWW-Authenticate please see https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/WWW-Authenticate */ - export interface AuthenticationWWWAuthenticateRequest { + export interface AuthenticationWwwAuthenticateRequest { /** * The raw WWW-Authenticate header value that triggered this challenge. * This will be parsed by the authentication provider to extract the necessary @@ -30,13 +30,12 @@ declare module 'vscode' { readonly wwwAuthenticate: string; /** - * @deprecated Use `wwwAuthenticate` instead. + * The fallback scopes to use if no scopes are found in the WWW-Authenticate header. */ - readonly challenge?: string; + readonly fallbackScopes?: readonly string[]; /** - * Optional scopes for the session. If not provided, the authentication provider - * may use default scopes or extract them from the challenge. + * @deprecated Use `fallbackScopes` instead. */ readonly scopes?: readonly string[]; } @@ -59,7 +58,7 @@ declare module 'vscode' { * @param options The {@link AuthenticationGetSessionOptions} to use * @returns A thenable that resolves to an authentication session */ - export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, options: AuthenticationGetSessionOptions & { /** */createIfNone: true | AuthenticationGetSessionPresentationOptions }): Thenable; + export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWwwAuthenticateRequest, options: AuthenticationGetSessionOptions & { /** */createIfNone: true | AuthenticationGetSessionPresentationOptions }): Thenable; /** * Get an authentication session matching the desired scopes or request. Rejects if a provider with providerId is not @@ -77,7 +76,7 @@ declare module 'vscode' { * @param options The {@link AuthenticationGetSessionOptions} to use * @returns A thenable that resolves to an authentication session */ - export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, options: AuthenticationGetSessionOptions & { /** literal-type defines return type */forceNewSession: true | AuthenticationGetSessionPresentationOptions | AuthenticationForceNewSessionOptions }): Thenable; + export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWwwAuthenticateRequest, options: AuthenticationGetSessionOptions & { /** literal-type defines return type */forceNewSession: true | AuthenticationGetSessionPresentationOptions | AuthenticationForceNewSessionOptions }): Thenable; /** * Get an authentication session matching the desired scopes or request. Rejects if a provider with providerId is not @@ -95,7 +94,7 @@ declare module 'vscode' { * @param options The {@link AuthenticationGetSessionOptions} to use * @returns A thenable that resolves to an authentication session or undefined if a silent flow was used and no session was found */ - export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWWWAuthenticateRequest, options?: AuthenticationGetSessionOptions): Thenable; + export function getSession(providerId: string, scopeListOrRequest: ReadonlyArray | AuthenticationWwwAuthenticateRequest, options?: AuthenticationGetSessionOptions): Thenable; } @@ -141,7 +140,7 @@ declare module 'vscode' { * Optional scopes for the session. If not provided, the authentication provider * may extract scopes from the challenges or use default scopes. */ - readonly scopes?: readonly string[]; + readonly fallbackScopes?: readonly string[]; } /**