/** * Authentication client for MCP server * Handles custom API key validation and OAuth token retrieval */ interface APIKeyValidationResponse { valid: boolean; portal_id: string; key_name: string; scopes: string[]; authenticated_at: string; } interface OAuthTokenResponse { success: boolean; data: { access_token: string; portal_id: string; token_type: string; expires_at: number; scopes: string[]; }; } export class AuthClient { private apiKey: string; private baseUrl: string; constructor(apiKey: string, baseUrl?: string) { this.apiKey = apiKey; this.baseUrl = baseUrl || process.env.MORPHED_API_URL || 'https://morphed.io'; } /** * Validate the MCP API key and get portal context */ async validateAPIKey(): Promise { try { const response = await fetch(`${this.baseUrl}/api/mcp/validate`, { method: 'GET', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`API key validation failed: ${response.status} ${response.statusText}`); } const data = await response.json(); return data; } catch (error) { console.error('API key validation failed:', error); throw new Error(`Failed to validate API key: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get OAuth token for the portal associated with this API key */ async getOAuthToken(): Promise { try { // First validate the API key to get portal context const validation = await this.validateAPIKey(); if (!validation.valid) { throw new Error('Invalid API key'); } // Get OAuth token for the portal const response = await fetch(`${this.baseUrl}/api/mcp/oauth/token?portalId=${validation.portal_id}`, { method: 'GET', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`OAuth token fetch failed: ${response.status} ${response.statusText}`); } const data: OAuthTokenResponse = await response.json(); if (!data.success || !data.data.access_token) { throw new Error('No OAuth token available for this portal'); } console.log(`Retrieved OAuth token for portal ${validation.portal_id}`); return data.data.access_token; } catch (error) { console.error('OAuth token retrieval failed:', error); throw new Error(`Failed to get OAuth token: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Get portal ID associated with this API key */ async getPortalId(): Promise { const validation = await this.validateAPIKey(); return validation.portal_id; } }