diff --git a/package.json b/package.json index 509fd3a40c7..ebd3fa44f35 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.106.0", - "distro": "83bba123096af4c03a5f4419dc4e7f33d14e354c", + "distro": "cf7a6d44d8299723d955936df569ea424e6b68fd", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/base/common/oauth.ts b/src/vs/base/common/oauth.ts index 00dae1f86ec..c808bf818b9 100644 --- a/src/vs/base/common/oauth.ts +++ b/src/vs/base/common/oauth.ts @@ -257,6 +257,13 @@ export interface IAuthorizationServerMetadata { * OPTIONAL. JSON array containing a list of PKCE code challenge methods supported. */ code_challenge_methods_supported?: string[]; + + /** + * OPTIONAL. Boolean flag indicating whether the authorization server supports the + * client_id_metadata document. + * ref https://datatracker.ietf.org/doc/html/draft-parecki-oauth-client-id-metadata-document-03 + */ + client_id_metadata_document_supported?: boolean; } /** diff --git a/src/vs/base/common/product.ts b/src/vs/base/common/product.ts index c9be42c6a66..2b552bdde7c 100644 --- a/src/vs/base/common/product.ts +++ b/src/vs/base/common/product.ts @@ -218,6 +218,7 @@ export interface IProductConfiguration { readonly chatEntitlementUrl: string; readonly mcpRegistryDataUrl: string; }; + readonly authClientIdMetadataUrl?: string; readonly 'configurationSync.store'?: ConfigurationSyncStore; diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index f15906e5c35..af3845c9307 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -28,6 +28,7 @@ import { IAuthorizationTokenResponse } from '../../../base/common/oauth.js'; import { IDynamicAuthenticationProviderStorageService } from '../../services/authentication/common/dynamicAuthenticationProviderStorage.js'; import { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js'; import { IQuickInputService } from '../../../platform/quickinput/common/quickInput.js'; +import { IProductService } from '../../../platform/product/common/productService.js'; export interface AuthenticationInteractiveOptions { detail?: string; @@ -112,6 +113,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu constructor( extHostContext: IExtHostContext, + @IProductService private readonly productService: IProductService, @IAuthenticationService private readonly authenticationService: IAuthenticationService, @IAuthenticationExtensionsService private readonly authenticationExtensionsService: IAuthenticationExtensionsService, @IAuthenticationAccessService private readonly authenticationAccessService: IAuthenticationAccessService, @@ -153,11 +155,15 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu // Auth Provider Id is a combination of the authorization server and the resource, if provided. const authProviderId = resource ? `${authorizationServer.toString(true)} ${resource.resource}` : authorizationServer.toString(true); const clientDetails = await this.dynamicAuthProviderStorageService.getClientRegistration(authProviderId); - const clientId = clientDetails?.clientId; + let clientId = clientDetails?.clientId; const clientSecret = clientDetails?.clientSecret; let initialTokens: (IAuthorizationTokenResponse & { created_at: number })[] | undefined = undefined; if (clientId) { initialTokens = await this.dynamicAuthProviderStorageService.getSessionsForDynamicAuthProvider(authProviderId, clientId); + // If we don't already have a client id, check if the server supports the Client Id Metadata flow (see docs on the property) + // and add the "client id" if so. + } else if (serverMetadata.client_id_metadata_document_supported) { + clientId = this.productService.authClientIdMetadataUrl; } return await this._proxy.$registerDynamicAuthProvider( authorizationServer,