Skip to main content

Overview

Platform Connections enable Genie Helper to authenticate with creator platforms for scraping stats and publishing content. Credentials are encrypted with AES-256-GCM and stored in the Directus creator_profiles collection. Supported Platforms:
  • OnlyFans
  • Fansly
  • Pornhub
  • XVideos
  • Instagram
  • TikTok
  • X (Twitter)
  • Reddit
  • YouTube

Connection Methods

Flow:
  1. User logs into platform via browser
  2. GenieHelper browser extension captures session cookies
  3. Cookies encrypted and stored in platform_sessions collection
  4. Stagehand injects cookies to bypass login screens
Advantages:
  • No credential storage required
  • Works with 2FA/SSO platforms
  • Session reuse reduces bot detection risk
  • No password exposure
See: Browser Extension for setup.

2. Username/Password (Legacy)

Flow:
  1. User enters credentials in dashboard /app/platforms
  2. Credentials encrypted with AES-256-GCM
  3. Stored in creator_profiles.credentials field
  4. Stagehand uses credentials for automated login
Disadvantages:
  • Fails on platforms with 2FA
  • Requires password exposure
  • Higher bot detection risk
  • Manual login automation brittle
When to Use:
  • Platforms without 2FA
  • Initial setup before cookie capture
  • Fallback if cookies expire

3. OAuth (Planned)

Roadmap: Phase 9E Supported Platforms:
  • Google (YouTube)
  • X (Twitter)
Flow:
  1. User clicks “Connect with OAuth” in dashboard
  2. Redirected to platform OAuth consent screen
  3. Platform issues access token + refresh token
  4. Tokens encrypted and stored in creator_profiles.credentials
  5. Dashboard polls for OAuth callback
Status: Not implemented (see README TODO section).

Credential Storage

Creator Profiles Collection

Collection: creator_profiles

Credentials Field Format

Unencrypted Payload (before encryption):
Encrypted Storage (in Directus):
Envelope Format: v1:<iv_b64>:<tag_b64>:<ciphertext_b64>

Platform Sessions Collection

Collection: platform_sessions Cookie Format (before encryption):

Encryption Implementation

AES-256-GCM

Genie Helper uses AES-256-GCM (Galois/Counter Mode) for authenticated encryption: Security Properties:
  • Confidentiality: Credentials unreadable without key
  • Integrity: Tampered ciphertext rejected during decryption
  • Authentication: Additional Authenticated Data (AAD) prevents context swapping
Key Material:
  • Encryption Key: 32 bytes (256 bits)
  • IV (Initialization Vector): 12 bytes (96 bits), random per encryption
  • Auth Tag: 16 bytes (128 bits), generated during encryption
  • AAD: “agentx-v1” (fixed context string)

Encryption Module

Location: /home/daytona/workspace/source/server/utils/credentialsCrypto.js:1 Functions:
  • encryptJSON(obj): Encrypts object → returns envelope
  • decryptJSON(envelope): Decrypts envelope → returns object
Environment Variables:

Encryption Process

encryptJSON(obj) Flow:

Decryption Process

decryptJSON(envelope) Flow:

Key Generation

To generate a new encryption key:
Add to .env:
CRITICAL: Store this key securely. Loss of key = permanent credential loss.

Dashboard Integration

Connecting a Platform

Page: /app/platforms Flow:
  1. User clicks “Add Platform”
  2. Selects platform from dropdown
  3. Enters username + password (or clicks “Capture Cookies”)
  4. Dashboard calls /api/credentials/store-platform-credentials
  5. Server encrypts credentials via encryptJSON()
  6. Inserts creator_profiles record with encrypted credentials field
  7. Dashboard shows success + scrape configuration options
Frontend Code (dashboard/src/pages/PlatformConnect/index.jsx):

Credentials API

Endpoint: /api/credentials/store-platform-credentials Location: /home/daytona/workspace/source/server/endpoints/api/credentials.js:1 Request:
Response:
Server Implementation:

Scraping Configuration

Enabling Auto-Scrape

After connecting a platform, configure automated scraping: Dashboard UI:
  • Scrape Enabled: Toggle to enable/disable
  • Frequency: Cron expression or preset (every 6 hours, daily, etc.)
  • Last Scraped: Timestamp of last successful scrape
  • Status: idle, running, success, error
PATCH Request:

Cron Expressions

Common Patterns: Scheduler: The post_scheduler worker (media-worker) polls creator_profiles for enabled scrapes. Implementation (media-worker/index.js):

Manual Scraping

Trigger from Dashboard

Button: “Scrape Now” on /app/dashboard Flow:
  1. User clicks “Scrape Now”
  2. Dashboard checks for valid platform_sessions record
  3. If no cookies: creates hitl_sessions record → shows yellow banner
  4. If cookies exist: enqueues scrape_profile job via /api/queue/enqueue
  5. Dashboard polls media_jobs collection for job status
  6. On completion: shows scraped media count + updates creator_profiles.last_scraped_at
Frontend Code:

Security Best Practices

Key Rotation

To rotate the encryption key:
  1. Generate New Key:
  2. Re-encrypt All Credentials:
  3. Update .env on Server
  4. Restart Services:

Backup & Recovery

Backup Encryption Key:
  1. Store CREDENTIALS_ENC_KEY_B64 in password manager
  2. Add to encrypted .env.backup file
  3. Store in separate location from server
Recovery: If key is lost:
  • All encrypted credentials are permanently unrecoverable
  • Users must re-connect all platforms
  • No decryption method exists without original key

Access Control

Environment Permissions:
Directus Permissions:
  • creator_profiles.credentials: Never expose via API to frontend
  • Dashboard should only display connection status, never raw credentials
  • Admin role can view encrypted envelope (but not decrypt without key)
Server-Side Only:
  • Encryption/decryption always happens server-side
  • Browser extension POSTs cookies to server (server encrypts)
  • Dashboard never receives decrypted credentials

Troubleshooting

”Invalid Credential Envelope” Error

Cause: Encryption key mismatch or corrupted data. Fix:
  1. Verify CREDENTIALS_ENC_KEY_B64 matches key used during encryption
  2. Check envelope format starts with v1:
  3. Test decryption manually:

Scrape Job Stuck in “Running”

Cause: Stagehand session crashed or hung. Fix:
  1. Check Stagehand logs: pm2 logs stagehand-server
  2. Restart Stagehand: pm2 restart stagehand-server
  3. Manually update job status:

“No Cookies Found” During Scrape

Cause: platform_sessions record missing or expired. Fix:
  1. Check platform_sessions collection for matching creator_profile_id + platform
  2. If missing: create HITL session (dashboard does this automatically)
  3. If expired: re-capture cookies via browser extension
  4. Verify cookie expires_at is in the future

Platform Login Fails with Cookies

Cause: Cookies expired, platform session invalidated, or IP change. Fix:
  1. Log into platform manually in browser
  2. Re-capture cookies via extension
  3. Trigger scrape again
  4. If still fails: platform may have changed auth mechanism (check for OAuth migration)