mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 00:15:23 +02:00
Handle re-registration of OAuth clients when redirect_uri changes
This commit is contained in:
parent
2fcf8c5419
commit
016e96849e
2 changed files with 74 additions and 7 deletions
|
|
@ -1610,6 +1610,65 @@ describe('MCPOAuthHandler - Configurable OAuth Metadata', () => {
|
|||
// Should have fallen back to registerClient
|
||||
expect(mockRegisterClient).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should re-register when stored redirect_uri differs from current configuration', async () => {
|
||||
const existingClientInfo = {
|
||||
client_id: 'existing-client-id',
|
||||
client_secret: 'existing-client-secret',
|
||||
redirect_uris: ['http://old-domain.com/api/mcp/test-server/oauth/callback'],
|
||||
token_endpoint_auth_method: 'client_secret_basic',
|
||||
};
|
||||
|
||||
mockGetClientInfoAndMetadata.mockResolvedValueOnce({
|
||||
clientInfo: existingClientInfo,
|
||||
clientMetadata: {},
|
||||
});
|
||||
|
||||
mockDiscoverOAuthProtectedResourceMetadata.mockRejectedValueOnce(
|
||||
new Error('No resource metadata'),
|
||||
);
|
||||
|
||||
mockDiscoverAuthorizationServerMetadata.mockResolvedValueOnce({
|
||||
issuer: 'https://example.com',
|
||||
authorization_endpoint: 'https://example.com/authorize',
|
||||
token_endpoint: 'https://example.com/token',
|
||||
registration_endpoint: 'https://example.com/register',
|
||||
response_types_supported: ['code'],
|
||||
jwks_uri: 'https://example.com/.well-known/jwks.json',
|
||||
subject_types_supported: ['public'],
|
||||
id_token_signing_alg_values_supported: ['RS256'],
|
||||
} as AuthorizationServerMetadata);
|
||||
|
||||
mockRegisterClient.mockResolvedValueOnce({
|
||||
client_id: 'new-client-id',
|
||||
client_secret: 'new-client-secret',
|
||||
redirect_uris: ['http://localhost:3080/api/mcp/test-server/oauth/callback'],
|
||||
});
|
||||
|
||||
mockStartAuthorization.mockResolvedValueOnce({
|
||||
authorizationUrl: new URL('https://example.com/authorize?client_id=new-client-id'),
|
||||
codeVerifier: 'test-code-verifier',
|
||||
});
|
||||
|
||||
await MCPOAuthHandler.initiateOAuthFlow(
|
||||
'test-server',
|
||||
'https://example.com/mcp',
|
||||
'user-123',
|
||||
{},
|
||||
undefined,
|
||||
mockFindToken,
|
||||
);
|
||||
|
||||
expect(mockRegisterClient).toHaveBeenCalled();
|
||||
expect(mockStartAuthorization).toHaveBeenCalledWith(
|
||||
'https://example.com/mcp',
|
||||
expect.objectContaining({
|
||||
clientInformation: expect.objectContaining({
|
||||
client_id: 'new-client-id',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fallback OAuth Metadata (Legacy Server Support)', () => {
|
||||
|
|
|
|||
|
|
@ -496,10 +496,10 @@ export class MCPOAuthHandler {
|
|||
`[MCPOAuth] OAuth metadata discovered, auth server URL: ${sanitizeUrlForLogging(authServerUrl)}`,
|
||||
);
|
||||
|
||||
const redirectUri = this.getDefaultRedirectUri(serverName);
|
||||
logger.debug(`[MCPOAuth] Registering OAuth client with redirect URI: ${redirectUri}`);
|
||||
/** Dynamic client registration based on the discovered metadata */
|
||||
const redirectUri = config?.redirect_uri || this.getDefaultRedirectUri(serverName);
|
||||
logger.debug(`[MCPOAuth] Resolving OAuth client with redirect URI: ${redirectUri}`);
|
||||
|
||||
// Before registering, check if we already have a valid client registration
|
||||
let clientInfo: OAuthClientInformation | undefined;
|
||||
|
||||
if (findToken) {
|
||||
|
|
@ -510,10 +510,18 @@ export class MCPOAuthHandler {
|
|||
findToken,
|
||||
});
|
||||
if (existing?.clientInfo?.client_id) {
|
||||
logger.debug(
|
||||
`[MCPOAuth] Reusing existing client registration: ${existing.clientInfo.client_id}`,
|
||||
);
|
||||
clientInfo = existing.clientInfo;
|
||||
const existingClient = existing.clientInfo as OAuthClientInformation;
|
||||
const storedRedirectUri = existingClient.redirect_uris?.[0];
|
||||
if (storedRedirectUri && storedRedirectUri !== redirectUri) {
|
||||
logger.debug(
|
||||
`[MCPOAuth] Stored redirect_uri "${storedRedirectUri}" differs from current "${redirectUri}", will re-register`,
|
||||
);
|
||||
} else {
|
||||
logger.debug(
|
||||
`[MCPOAuth] Reusing existing client registration: ${existingClient.client_id}`,
|
||||
);
|
||||
clientInfo = existingClient;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue