Awesome-omni-skill oauth-platform-integration
Add new OAuth platform connectors to Twin Me Soul Signature Platform. Use when the user wants to integrate a new platform (Spotify, Netflix, LinkedIn, TikTok, etc.) for soul signature data extraction.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/testing-security/oauth-platform-integration" ~/.claude/skills/diegosouzapw-awesome-omni-skill-oauth-platform-integration && rm -rf "$T"
skills/testing-security/oauth-platform-integration/SKILL.mdOAuth Platform Integration Skill
This skill streamlines adding new OAuth-enabled platforms to the Twin Me platform for authentic soul signature data collection.
When to Use This Skill
Trigger this skill when:
- User requests adding a new platform connector (e.g., "Add Spotify integration")
- Implementing OAuth flow for entertainment or professional platforms
- Setting up data extraction for a new service
Prerequisites
Before adding a platform, verify:
- Platform has a public OAuth 2.0 API
- OAuth credentials obtained (CLIENT_ID, CLIENT_SECRET)
- Platform API documentation accessible
Integration Checklist
1. OAuth App Configuration (External)
For each platform, configure OAuth app settings:
Required redirect URIs:
- Local development:
http://localhost:8086/oauth/callback - Production:
https://twin-ai-learn.vercel.app/oauth/callback
Required OAuth scopes (platform-specific):
- Spotify:
,user-read-recently-played
,user-top-readuser-library-read - Discord:
,identify
,guildsmessages.read - GitHub:
,user
(read-only)repo - LinkedIn:
,r_liteprofiler_emailaddress - Netflix: (No official API - requires browser extension approach)
2. Environment Variables
Add to
.env file:
# [PLATFORM_NAME] OAuth [PLATFORM]_CLIENT_ID=your-client-id [PLATFORM]_CLIENT_SECRET=your-client-secret
Example:
SPOTIFY_CLIENT_ID=abc123def456 SPOTIFY_CLIENT_SECRET=xyz789uvw012
3. Platform API Configuration
Add platform config to
api/services/platformAPIMappings.js:
const PLATFORM_CONFIGS = { // ... existing platforms [newPlatform]: { name: 'Platform Display Name', authUrl: 'https://platform.com/oauth/authorize', tokenUrl: 'https://platform.com/oauth/token', scopes: ['scope1', 'scope2', 'scope3'], apiBaseUrl: 'https://api.platform.com/v1', // OAuth endpoints endpoints: { userProfile: '/me', recentActivity: '/me/recent', topItems: '/me/top', }, // Token handling tokenType: 'Bearer', // or 'OAuth' refreshable: true, // Does platform support token refresh? // Rate limiting rateLimit: { requests: 100, window: 3600, // seconds }, }, };
4. OAuth Route Implementation
Add OAuth routes to
api/routes/entertainment-connectors.js (or mcp-connectors.js for professional platforms):
// Initiate OAuth flow router.get('/connect/:platform', async (req, res) => { const { platform } = req.params; const userId = req.user.id; // From JWT auth middleware const config = PLATFORM_CONFIGS[platform]; if (!config) { return res.status(404).json({ error: 'Platform not supported' }); } // Generate OAuth state for security const state = crypto.randomBytes(16).toString('hex'); await saveOAuthState(userId, platform, state); // Build authorization URL const authUrl = new URL(config.authUrl); authUrl.searchParams.append('client_id', process.env[`${platform.toUpperCase()}_CLIENT_ID`]); authUrl.searchParams.append('redirect_uri', `${process.env.CLIENT_URL}/oauth/callback`); authUrl.searchParams.append('response_type', 'code'); authUrl.searchParams.append('scope', config.scopes.join(' ')); authUrl.searchParams.append('state', state); res.json({ authUrl: authUrl.toString() }); }); // Handle OAuth callback router.get('/callback/:platform', async (req, res) => { const { platform } = req.params; const { code, state } = req.query; try { // Verify state to prevent CSRF const validState = await verifyOAuthState(state); if (!validState) { throw new Error('Invalid OAuth state'); } // Exchange code for tokens const tokens = await exchangeCodeForTokens(platform, code); // Encrypt and store tokens await savePlatformConnection(validState.userId, platform, { accessToken: tokens.access_token, refreshToken: tokens.refresh_token, expiresAt: Date.now() + (tokens.expires_in * 1000), }); // Redirect back to frontend res.redirect(`${process.env.CLIENT_URL}/get-started?connected=${platform}`); } catch (error) { console.error(`OAuth callback error for ${platform}:`, error); res.redirect(`${process.env.CLIENT_URL}/get-started?error=${platform}`); } });
5. Data Extraction Service
Add extraction logic to
api/services/dataExtraction.js:
async function extract[PlatformName]Data(userId) { const connection = await getPlatformConnection(userId, '[platform]'); if (!connection || !connection.accessToken) { throw new Error('Platform not connected'); } try { // Decrypt access token const accessToken = decryptToken(connection.accessToken); // Fetch data from platform API const config = PLATFORM_CONFIGS['[platform]']; const response = await axios.get( `${config.apiBaseUrl}${config.endpoints.recentActivity}`, { headers: { 'Authorization': `${config.tokenType} ${accessToken}`, }, } ); // Transform platform data to soul signature format const extractedData = transformPlatformData(response.data, '[platform]'); // Save to database await saveSoulData(userId, { platform: '[platform]', dataType: 'recent_activity', rawData: response.data, extractedPatterns: extractedData, extractedAt: new Date(), }); return { success: true, itemsExtracted: extractedData.length, platform: '[platform]', }; } catch (error) { // Handle token expiration if (error.response?.status === 401) { await markConnectionRequiresReauth(userId, '[platform]'); return { success: false, requiresReauth: true, error: 'Token expired - reconnection required', }; } throw error; } }
6. Frontend Platform Card
Add platform card to
src/pages/GetStarted.tsx:
const platformConfig = { // ... existing platforms [newPlatform]: { name: 'Platform Name', icon: PlatformIcon, // Import from lucide-react or custom SVG description: 'What this platform reveals about your soul signature', setupTime: '10 seconds setup', category: 'essential' | 'optional', // Determines which section insights: [ 'Primary Insight Type', 'Secondary Insight Type', '+N more', ], color: '#BRAND_COLOR', // Platform brand color for UI }, };
7. Database Schema Update
Ensure
data_connectors table supports the new platform:
-- Platform connection already exists in schema -- Just verify the platform name is consistent: SELECT * FROM data_connectors WHERE provider = '[platform_name]'; -- If adding custom metadata fields: ALTER TABLE data_connectors ADD COLUMN IF NOT EXISTS platform_metadata JSONB DEFAULT '{}'::jsonb;
8. Soul Signature Mapping
Define how platform data maps to personality traits in
api/services/soulSignatureAnalyzer.js:
const PLATFORM_TRAIT_MAPPINGS = { // ... existing mappings [newPlatform]: { // Big Five personality traits traits: { openness: (data) => calculateOpenness(data.genres, data.diversity), conscientiousness: (data) => calculateConscientiousness(data.organizationLevel), extraversion: (data) => calculateExtraversion(data.socialActivity), agreeableness: (data) => calculateAgreeableness(data.interactions), neuroticism: (data) => calculateNeuroticism(data.emotionalContent), }, // Communication style communication: (data) => analyzeCommunicationStyle(data.messages), // Interests and preferences interests: (data) => extractInterests(data.content), }, };
Testing Checklist
After implementation, verify:
- OAuth flow redirects correctly (local + production)
- Tokens encrypted/decrypted successfully
- Connection shows "Connected" status in UI
- Data extraction endpoint returns items
- No token decryption errors in logs
- Platform appears in Soul Signature dashboard
- Personality traits updated with platform data
Common Pitfalls
Redirect URI Mismatch
Error: "redirect_uri did not match" Solution: Ensure OAuth app has BOTH localhost AND production URLs configured
Token Encryption Key Mismatch
Error: "Unsupported state or unable to authenticate data" Solution: Use current
ENCRYPTION_KEY from .env, clear old tokens before reconnecting
Rate Limiting
Error: 429 Too Many Requests Solution: Implement exponential backoff, respect platform rate limits in
PLATFORM_CONFIGS
Scope Permissions
Error: 403 Forbidden on specific endpoints Solution: Verify OAuth scopes match required API permissions
Platform-Specific Notes
Spotify
- Requires both user authorization AND token refresh flow
- Rate limit: 180 requests per minute
- Best practice: Batch requests for user's top tracks/artists
Discord
- Guilds endpoint requires
scopeguilds - Message access limited to servers bot has joined
- Rate limit: 50 requests per second globally
GitHub
- Only allows ONE callback URL per OAuth app
- Recommendation: Create separate dev OAuth app for localhost
- Rate limit: 5,000 requests/hour for authenticated requests
- V2 API requires separate permissions for profile vs email
- Limited data access compared to V1 (deprecated)
- Rate limit: varies by endpoint
Netflix / Streaming Platforms
Note: Most streaming platforms (Netflix, HBO, Disney+) have NO public API
Alternative Approach: Browser extension for data extraction
- See
directorybrowser-extension/ - Uses content scripts to capture viewing history
- Sends data to backend via secure API
File References
For detailed implementation examples, see:
- OAuth Config:
./oauth-config-examples.md - Extraction Patterns:
./extraction-patterns.md - API Rate Limiting:
./rate-limiting-guide.md
Quick Start Template
Use the provided script to scaffold a new platform integration:
cd twin-me node skills/oauth-platform-integration/scripts/scaffold-platform.js <platform-name>
This generates:
- Environment variable template
- Platform config skeleton
- OAuth route boilerplate
- Extraction service stub
- Frontend platform card
- Test suite
Success Criteria
Platform integration is complete when:
- ✅ OAuth flow works end-to-end (local + production)
- ✅ Tokens stored encrypted in database
- ✅ Data extraction returns > 0 items
- ✅ Platform appears as "Connected" in UI
- ✅ Soul signature updates with new data
- ✅ No console errors or token decryption issues
Skill Version: 1.0.0 Last Updated: January 18, 2025 Maintainer: Twin Me Development Team