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.
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:
From this, we plan on mapping issuers to auth providers. So for example, if we see an issuer like so:
we will use the
githubauth provider.microsoftis where it gets interesting... because technically it is N issuers all it one based on the path of issuer.These are all valid issuers. By default, VS Code uses
organizations, but you can override it with a secret scope:VSCODE_TENANT:<value>so likeVSCODE_TENANT:commonorVSCODE_TENANT:<guid>.The issuer is then used to make urls like:
which is the login page you see in your browser.
and
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_TENANTWe have a
resolveMcpAuthenticationScopeswhich is passed in theauthorizationServer(akaissuer) and thescopes(akascopes_supported)This will resolve the correct scopes. So:
https://login.microsoftonline.com/consumers/v2.0["api://foo/bar"]resolves to:
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...
and then we implement this in the Microsoft auth provider where the tenant is extracted from
issuerand used as a replacement forVSCODE_TENANT.