[auth] Add resource compatibility to debugger (RFC 8707) (#526)
* pass resource in auth debugger, reusing server url * throw error on resource url mismatch to match regular auth flow * lint & tests * add test * make authserver url make more sense * use latest typescript sdk * more lenient resource checking * pick resource, and store in state * fixing tests and types * [auth] use sdk function for selecting resource (#537) * use sdk function * bump typescript sdk * fix some tests
This commit is contained in:
parent
2ef41ab58a
commit
5db64265ce
2 changed files with 34 additions and 22 deletions
|
|
@ -30,6 +30,7 @@ export interface AuthDebuggerState {
|
|||
oauthStep: OAuthStep;
|
||||
resourceMetadata: OAuthProtectedResourceMetadata | null;
|
||||
resourceMetadataError: Error | null;
|
||||
resource: URL | null;
|
||||
authServerUrl: URL | null;
|
||||
oauthMetadata: OAuthMetadata | null;
|
||||
oauthClientInfo: OAuthClientInformationFull | OAuthClientInformation | null;
|
||||
|
|
@ -47,6 +48,7 @@ export const EMPTY_DEBUGGER_STATE: AuthDebuggerState = {
|
|||
oauthMetadata: null,
|
||||
resourceMetadata: null,
|
||||
resourceMetadataError: null,
|
||||
resource: null,
|
||||
authServerUrl: null,
|
||||
oauthClientInfo: null,
|
||||
authorizationUrl: null,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
startAuthorization,
|
||||
exchangeAuthorization,
|
||||
discoverOAuthProtectedResourceMetadata,
|
||||
selectResourceURL,
|
||||
} from "@modelcontextprotocol/sdk/client/auth.js";
|
||||
import {
|
||||
OAuthMetadataSchema,
|
||||
|
|
@ -29,17 +30,15 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
|||
metadata_discovery: {
|
||||
canTransition: async () => true,
|
||||
execute: async (context) => {
|
||||
let authServerUrl = new URL(context.serverUrl);
|
||||
// Default to discovering from the server's URL
|
||||
let authServerUrl = new URL("/", context.serverUrl);
|
||||
let resourceMetadata: OAuthProtectedResourceMetadata | null = null;
|
||||
let resourceMetadataError: Error | null = null;
|
||||
try {
|
||||
resourceMetadata = await discoverOAuthProtectedResourceMetadata(
|
||||
context.serverUrl,
|
||||
);
|
||||
if (
|
||||
resourceMetadata &&
|
||||
resourceMetadata.authorization_servers?.length
|
||||
) {
|
||||
if (resourceMetadata?.authorization_servers?.length) {
|
||||
authServerUrl = new URL(resourceMetadata.authorization_servers[0]);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -50,6 +49,13 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
|||
}
|
||||
}
|
||||
|
||||
const resource: URL | undefined = await selectResourceURL(
|
||||
context.serverUrl,
|
||||
context.provider,
|
||||
// we default to null, so swap it for undefined if not set
|
||||
resourceMetadata ?? undefined,
|
||||
);
|
||||
|
||||
const metadata = await discoverOAuthMetadata(authServerUrl);
|
||||
if (!metadata) {
|
||||
throw new Error("Failed to discover OAuth metadata");
|
||||
|
|
@ -58,6 +64,7 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
|||
context.provider.saveServerMetadata(parsedMetadata);
|
||||
context.updateState({
|
||||
resourceMetadata,
|
||||
resource,
|
||||
resourceMetadataError,
|
||||
authServerUrl,
|
||||
oauthMetadata: parsedMetadata,
|
||||
|
|
@ -113,6 +120,7 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
|||
clientInformation,
|
||||
redirectUrl: context.provider.redirectUrl,
|
||||
scope,
|
||||
resource: context.state.resource ?? undefined,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
@ -163,6 +171,7 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
|||
authorizationCode: context.state.authorizationCode,
|
||||
codeVerifier,
|
||||
redirectUri: context.provider.redirectUrl,
|
||||
resource: context.state.resource ?? undefined,
|
||||
});
|
||||
|
||||
context.provider.saveTokens(tokens);
|
||||
|
|
|
|||
Loading…
Reference in a new issue