From 286a752f5ebce04eff8a3407ea32b196a6774c60 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt <2644648+TylerLeonhardt@users.noreply.github.com> Date: Tue, 14 Oct 2025 16:06:20 -0700 Subject: [PATCH] Use CIMD if supported (#271403) * Use CIMD if supported If the Authorization Server we are auth'ing against supports the Client ID Metadata auth flow, we use the client id metadata url from product.json as the client id in auth flows. Fixes https://github.com/microsoft/vscode/issues/270811 * Update src/vs/workbench/api/browser/mainThreadAuthentication.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- package.json | 2 +- src/vs/base/common/oauth.ts | 7 +++++++ src/vs/base/common/product.ts | 1 + src/vs/workbench/api/browser/mainThreadAuthentication.ts | 8 +++++++- 4 files changed, 16 insertions(+), 2 deletions(-) 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,