-
Notifications
You must be signed in to change notification settings - Fork 34.5k
Description
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
.