Skip to content

API to map auth server to auth provider #248775

@TylerLeonhardt

Description

@TylerLeonhardt

Context

In MCP land, and general OAuth land, we resolve what kind auth an MCP server needs by resolving to some OAuth Server Metadata. The important stuff in this is:

/**
 * Metadata about an OAuth 2.0 Authorization Server.
 */
export interface IAuthorizationServerMetadata {
	/**
	 * REQUIRED. The authorization server's issuer identifier URL that uses https scheme and has no query or fragment components.
	 */
	issuer: string;

	/**
	 * URL of the authorization server's authorization endpoint.
	 * This is REQUIRED unless no grant types are supported that use the authorization endpoint.
	 */
	authorization_endpoint?: string;

	/**
	 * URL of the authorization server's token endpoint.
	 * This is REQUIRED unless only the implicit grant type is supported.
	 */
	token_endpoint?: string;

	/**
	 * OPTIONAL. URL of the authorization server's OAuth 2.0 Dynamic Client Registration endpoint.
	 */
	registration_endpoint?: string;

	/**
	 * RECOMMENDED. JSON array containing a list of the OAuth 2.0 scope values supported.
	 */
	scopes_supported?: string[];

	/**
	 * REQUIRED. JSON array containing a list of the OAuth 2.0 response_type values supported.
	 */
	response_types_supported: string[];
}

From this, we plan on mapping issuers to auth providers. So for example, if we see an issuer like so:

https://github.com/login/oauth

we will use the github auth provider.

microsoft is where it gets interesting... because technically it is N issuers all it one based on the path of issuer.

https://login.microsoftonline.com/common/v2.0
https://login.microsoftonline.com/organizations/v2.0
https://login.microsoftonline.com/consumers/v2.0
https://login.microsoftonline.com/SOME_TENANT_ID/v2.0

These are all valid issuers. By default, VS Code uses organizations, but you can override it with a secret scope: VSCODE_TENANT:<value> so like VSCODE_TENANT:common or VSCODE_TENANT:<guid>.

The issuer is then used to make urls like:

https://login.microsoftonline.com/organizations/v2.0/authorize

which is the login page you see in your browser.
and

https://login.microsoftonline.com/organizations/v2.0/token

which is what you use to get a token after your browser redirects back to VS Code with a code.

Proposal

Option 1: Leaning in to VSCODE_TENANT

We have a resolveMcpAuthenticationScopes which is passed in the authorizationServer (aka issuer) and the scopes (aka scopes_supported)

declare module 'vscode' {
	export interface AuthenticationProvider {
		resolveMcpAuthenticationScopes?(authorizationServer: Uri, scopes: string[], token: CancellationToken): ProviderResult<string[]>;
	}
}

This will resolve the correct scopes. So:

  • issuer: https://login.microsoftonline.com/consumers/v2.0
  • ["api://foo/bar"]
    resolves to:
["api://foo/bar", "VSCODE_TENANT:consumers"]

Then the Microsoft auth provider will have the correct scopes to build the request.

Option 2: Making tenant first class

This is more work but maybe the direction we want to go...

	export interface AuthenticationProviderOptions {
		/**
		 * When specified, the caller of `getSession` will be able to override the issuer URL used to
		 * authenticate the user.
		 */
		readonly supportsIssuerOverride?: boolean;
	}

	export interface AuthenticationProviderSessionOptions {
		/**
		 * When specified, the authentication provider will use the provided issuer URL to
		 * authenticate the user. This is only used when a provider `supportsIssuerOverride` is set to true
		 */
		issuer?: Uri;
	}

	export interface AuthenticationGetSessionOptions {
		/**
		 * When specified, the authentication provider will use the provided issuer URL to
		 * authenticate the user. This is only used when a provider `supportsIssuerOverride` is set to true
		 */
		issuer?: Uri;
	}

and then we implement this in the Microsoft auth provider where the tenant is extracted from issuer and used as a replacement for VSCODE_TENANT.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions