mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-03 16:34:31 -07:00
85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi } from 'vitest';
|
|
import {
|
|
MCPOAuthClientProvider,
|
|
type OAuthAuthorizationResponse,
|
|
} from './mcp-oauth-provider.js';
|
|
import type {
|
|
OAuthClientInformation,
|
|
OAuthClientMetadata,
|
|
OAuthTokens,
|
|
} from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
|
|
describe('MCPOAuthClientProvider', () => {
|
|
const mockRedirectUrl = 'http://localhost:8090/callback';
|
|
const mockClientMetadata: OAuthClientMetadata = {
|
|
client_name: 'Test Client',
|
|
redirect_uris: [mockRedirectUrl],
|
|
grant_types: ['authorization_code', 'refresh_token'],
|
|
response_types: ['code'],
|
|
token_endpoint_auth_method: 'client_secret_post',
|
|
scope: 'test-scope',
|
|
};
|
|
const mockState = 'test-state-123';
|
|
|
|
describe('oauth flow', () => {
|
|
it('should support full OAuth flow', async () => {
|
|
const onRedirectMock = vi.fn();
|
|
const provider = new MCPOAuthClientProvider(
|
|
mockRedirectUrl,
|
|
mockClientMetadata,
|
|
mockState,
|
|
onRedirectMock,
|
|
);
|
|
|
|
// Step 1: Save client information
|
|
const clientInfo: OAuthClientInformation = {
|
|
client_id: 'my-client-id',
|
|
client_secret: 'my-client-secret',
|
|
};
|
|
provider.saveClientInformation(clientInfo);
|
|
|
|
// Step 2: Save code verifier
|
|
provider.saveCodeVerifier('my-code-verifier');
|
|
|
|
// Step 3: Set up callback server
|
|
const mockAuthResponse: OAuthAuthorizationResponse = {
|
|
code: 'authorization-code',
|
|
state: mockState,
|
|
};
|
|
const mockServer = {
|
|
port: Promise.resolve(8090),
|
|
waitForResponse: vi.fn().mockResolvedValue(mockAuthResponse),
|
|
close: vi.fn().mockResolvedValue(undefined),
|
|
};
|
|
provider.saveCallbackServer(mockServer);
|
|
|
|
// Step 4: Redirect to authorization
|
|
const authUrl = new URL('http://auth.example.com/authorize');
|
|
await provider.redirectToAuthorization(authUrl);
|
|
|
|
// Step 5: Save tokens after exchange
|
|
const tokens: OAuthTokens = {
|
|
access_token: 'final-access-token',
|
|
token_type: 'Bearer',
|
|
expires_in: 3600,
|
|
refresh_token: 'final-refresh-token',
|
|
};
|
|
provider.saveTokens(tokens);
|
|
|
|
// Verify all data is stored correctly
|
|
expect(provider.clientInformation()).toEqual(clientInfo);
|
|
expect(provider.codeVerifier()).toBe('my-code-verifier');
|
|
expect(provider.state()).toBe(mockState);
|
|
expect(provider.tokens()).toEqual(tokens);
|
|
expect(onRedirectMock).toHaveBeenCalledWith(authUrl);
|
|
expect(provider.getSavedCallbackServer()).toBe(mockServer);
|
|
});
|
|
});
|
|
});
|