Skip to main content
Glama
extract-auth-config.jsโ€ข14.6 kB
#!/usr/bin/env node /** * Authentication Configuration Extractor v1.0.0 * Extract authentication data from active Composer session for direct API use * * Purpose: One-time extraction of localStorage data to enable direct API authentication * Status: UTILITY - Preserves current v5.2.0 system, enables direct API alternative * * @version 1.0.0 (January 15, 2025) */ import { chromium } from 'playwright'; import fs from 'fs'; import path from 'path'; class AuthConfigExtractor { constructor() { this.extractedData = null; this.configPath = path.join(process.cwd(), 'config', 'direct-api-auth.json'); this.envPath = path.join(process.cwd(), 'config', 'direct-api.env'); } /** * Extract authentication configuration from active Composer session */ async extractFromActiveSession() { console.log('๐Ÿ” Authentication Configuration Extractor v1.0.0'); console.log('Purpose: Extract auth data for direct API authentication'); console.log('Status: Current v5.2.0 system preserved\n'); let browser = null; let page = null; try { console.log('๐Ÿ“ฑ Step 1: Opening EuConquisto Composer...'); browser = await chromium.launch({ headless: false, args: ['--disable-web-security', '--disable-features=VizDisplayCompositor'] }); page = await browser.newPage(); await page.goto('https://composer.euconquisto.com'); console.log('โณ Step 2: Waiting for authentication (please log in if needed)...'); console.log(' The browser will stay open for 30 seconds'); console.log(' Please ensure you are logged in to the Composer'); // Wait for potential authentication/loading await page.waitForTimeout(30000); console.log('๐Ÿ” Step 3: Extracting authentication data...'); const authData = await page.evaluate(() => { console.log('=== AUTH CONFIG EXTRACTION v1.0.0 ==='); const activeProject = localStorage.getItem('rdp-composer-active-project'); const userData = localStorage.getItem('rdp-composer-user-data'); console.log('Raw activeProject present:', !!activeProject); console.log('Raw userData present:', !!userData); if (!activeProject) { return { success: false, error: 'Active project data not found in localStorage' }; } if (!userData) { return { success: false, error: 'User data not found in localStorage' }; } let projectData, userDataParsed; try { projectData = JSON.parse(activeProject); userDataParsed = JSON.parse(userData); } catch (e) { return { success: false, error: 'Failed to parse localStorage data: ' + e.message }; } if (!projectData.uid) { return { success: false, error: 'Project UID not found in active project data' }; } if (!userDataParsed.access_token) { return { success: false, error: 'Access token not found in user data' }; } if (!projectData.connectors || !Array.isArray(projectData.connectors)) { return { success: false, error: 'Connectors array not found or invalid in project data' }; } // Extract all necessary data const result = { success: true, extractedAt: new Date().toISOString(), accessToken: userDataParsed.access_token, tokenType: userDataParsed.token_type || 'Bearer', projectUid: projectData.uid, projectName: projectData.name || 'Unknown Project', connectors: projectData.connectors.map(c => ({ uid: c.uid, name: c.name, type: c.type, permissions: c.permissions || [] })), userInfo: { uid: userDataParsed.uid, name: userDataParsed.name, email: userDataParsed.email }, // Store full raw data for debugging (tokens will be filtered out in output) rawUserData: userDataParsed, rawProjectData: projectData }; console.log('Extraction successful:', { projectUid: result.projectUid, projectName: result.projectName, connectorsCount: result.connectors.length, hasAccessToken: !!result.accessToken, tokenType: result.tokenType, tokenLength: result.accessToken.length, userUid: result.userInfo.uid, userName: result.userInfo.name }); return result; }); this.extractedData = authData; if (authData.success) { console.log('โœ… Authentication data extracted successfully!'); console.log(` Project: ${authData.projectName} (${authData.projectUid})`); console.log(` User: ${authData.userInfo.name} (${authData.userInfo.email})`); console.log(` Token Type: ${authData.tokenType}`); console.log(` Token Length: ${authData.accessToken.length} characters`); console.log(` Connectors: ${authData.connectors.length} available`); // List connectors console.log('\n๐Ÿ“ก Available Connectors:'); authData.connectors.forEach((connector, index) => { console.log(` ${index + 1}. ${connector.name || 'Unnamed'} (${connector.uid})`); if (connector.permissions.length > 0) { console.log(` Permissions: ${connector.permissions.join(', ')}`); } }); await this.saveConfiguration(); await this.generateEnvironmentFile(); await this.generateMCPConfig(); } else { console.log('โŒ Failed to extract authentication data:'); console.log(` Error: ${authData.error}`); } } catch (error) { console.error('โŒ Extraction error:', error.message); this.extractedData = { success: false, error: error.message }; } finally { if (browser) { console.log('\n๐Ÿ”„ Closing browser...'); await browser.close(); } } return this.extractedData; } /** * Save configuration to JSON file */ async saveConfiguration() { if (!this.extractedData || !this.extractedData.success) { return; } try { // Create config directory if it doesn't exist const configDir = path.dirname(this.configPath); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true }); } // Prepare config data (remove sensitive full tokens from saved file) const configData = { extractedAt: this.extractedData.extractedAt, tokenType: this.extractedData.tokenType, projectUid: this.extractedData.projectUid, projectName: this.extractedData.projectName, connectors: this.extractedData.connectors, userInfo: this.extractedData.userInfo, // Store token preview only in JSON file accessTokenPreview: this.extractedData.accessToken.substring(0, 50) + '...', note: 'Full access token stored in environment file for security' }; fs.writeFileSync(this.configPath, JSON.stringify(configData, null, 2)); console.log(`\n๐Ÿ’พ Configuration saved to: ${this.configPath}`); } catch (error) { console.error('โŒ Failed to save configuration:', error.message); } } /** * Generate environment file with full authentication data */ async generateEnvironmentFile() { if (!this.extractedData || !this.extractedData.success) { return; } try { const envContent = [ '# EuConquisto Composer Direct API Authentication', '# Generated on: ' + new Date().toISOString(), '# Source: Active Composer session localStorage extraction', '', '# Full JWT Access Token', `EUCONQUISTO_ACCESS_TOKEN="${this.extractedData.accessToken}"`, '', '# Token Type (usually Bearer)', `EUCONQUISTO_TOKEN_TYPE="${this.extractedData.tokenType}"`, '', '# Project Information', `EUCONQUISTO_PROJECT_UID="${this.extractedData.projectUid}"`, `EUCONQUISTO_PROJECT_NAME="${this.extractedData.projectName}"`, '', '# Connectors (JSON format)', `EUCONQUISTO_CONNECTORS='${JSON.stringify(this.extractedData.connectors)}'`, '', '# User Information (optional)', `EUCONQUISTO_USER_UID="${this.extractedData.userInfo.uid}"`, `EUCONQUISTO_USER_NAME="${this.extractedData.userInfo.name}"`, `EUCONQUISTO_USER_EMAIL="${this.extractedData.userInfo.email}"`, '', '# Usage:', '# source config/direct-api.env', '# export $(grep -v "^#" config/direct-api.env | xargs)', '' ].join('\n'); fs.writeFileSync(this.envPath, envContent); console.log(`๐Ÿ’พ Environment file saved to: ${this.envPath}`); console.log(' Use: source config/direct-api.env'); } catch (error) { console.error('โŒ Failed to generate environment file:', error.message); } } /** * Generate MCP configuration for Claude Desktop */ async generateMCPConfig() { if (!this.extractedData || !this.extractedData.success) { return; } try { const mcpConfig = { "mcpServers": { "euconquisto-composer-direct": { "command": "node", "args": [ "--max-old-space-size=4096", path.resolve(process.cwd(), "dist", "index.js") ], "env": { "NODE_ENV": "production", "EUCONQUISTO_ACCESS_TOKEN": this.extractedData.accessToken, "EUCONQUISTO_TOKEN_TYPE": this.extractedData.tokenType, "EUCONQUISTO_PROJECT_UID": this.extractedData.projectUid, "EUCONQUISTO_CONNECTORS": JSON.stringify(this.extractedData.connectors), "EUCONQUISTO_USER_UID": this.extractedData.userInfo.uid, "EUCONQUISTO_USER_NAME": this.extractedData.userInfo.name } } } }; const mcpConfigPath = path.join(process.cwd(), 'config', 'claude-desktop-config-direct-api.json'); fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2)); console.log(`๐Ÿ’พ MCP configuration saved to: ${mcpConfigPath}`); console.log(' Add this to your Claude Desktop configuration'); } catch (error) { console.error('โŒ Failed to generate MCP configuration:', error.message); } } /** * Test the extracted configuration */ async testConfiguration() { if (!this.extractedData || !this.extractedData.success) { console.log('โŒ No valid configuration to test'); return false; } console.log('\n๐Ÿงช Testing extracted configuration...'); try { // Import and test direct API client const { DirectAPIClient } = await import('../src/tools/direct-api-client.js'); const config = { accessToken: this.extractedData.accessToken, tokenType: this.extractedData.tokenType, projectUid: this.extractedData.projectUid, connectors: this.extractedData.connectors }; const client = new DirectAPIClient(config); const validationResult = await client.validateConnection(); if (validationResult.success) { console.log('โœ… Direct API configuration test successful!'); console.log('๐ŸŽฏ Direct API authentication is ready for use'); return true; } else { console.log('โŒ Direct API configuration test failed:'); console.log(' Error:', validationResult.error); return false; } } catch (error) { console.log('โŒ Configuration test error:', error.message); return false; } } /** * Output summary and next steps */ outputSummary() { console.log('\n' + '='.repeat(70)); console.log('๐Ÿ“‹ AUTHENTICATION EXTRACTION SUMMARY'); console.log('='.repeat(70)); if (this.extractedData && this.extractedData.success) { console.log('\nโœ… EXTRACTION SUCCESSFUL'); console.log(` Project: ${this.extractedData.projectName}`); console.log(` User: ${this.extractedData.userInfo.name}`); console.log(` Connectors: ${this.extractedData.connectors.length} available`); console.log(` Extracted: ${this.extractedData.extractedAt}`); console.log('\n๐Ÿ“ FILES CREATED:'); console.log(` Configuration: ${this.configPath}`); console.log(` Environment: ${this.envPath}`); console.log(` MCP Config: config/claude-desktop-config-direct-api.json`); console.log('\n๐ŸŽฏ NEXT STEPS:'); console.log(' 1. Load environment: source config/direct-api.env'); console.log(' 2. Test direct API: node src/tools/direct-api-client.js'); console.log(' 3. Update Claude Desktop config if desired'); console.log(' 4. Consider replacing JWT redirect server with direct API calls'); console.log('\n๐Ÿ” SECURITY NOTE:'); console.log(' โ€ข Full JWT token stored in config/direct-api.env'); console.log(' โ€ข Add config/direct-api.env to .gitignore'); console.log(' โ€ข Token expires - re-extract when needed'); } else { console.log('\nโŒ EXTRACTION FAILED'); if (this.extractedData) { console.log(` Error: ${this.extractedData.error}`); } console.log('\n๐ŸŽฏ TROUBLESHOOTING:'); console.log(' 1. Ensure you are logged into EuConquisto Composer'); console.log(' 2. Wait for the page to fully load before extraction'); console.log(' 3. Check browser console for localStorage data'); console.log(' 4. Verify network connectivity to composer.euconquisto.com'); } console.log('\n๐Ÿ“Œ CURRENT PROJECT STATUS:'); console.log(' v5.2.0 FULLY OPERATIONAL system is preserved and unchanged'); console.log(' This extraction enables optional direct API approach'); console.log('\n' + '='.repeat(70) + '\n'); } } // Execute extraction if run directly if (import.meta.url === `file://${process.argv[1]}`) { const extractor = new AuthConfigExtractor(); extractor.extractFromActiveSession() .then(async (result) => { if (result && result.success) { await extractor.testConfiguration(); } extractor.outputSummary(); }) .catch(error => { console.error('โŒ Extraction process error:', error.message); process.exit(1); }); } export { AuthConfigExtractor };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server