# LinkedIn Auto-Posting Setup Guide This guide walks you through setting up the LinkedIn auto-posting feature. ## Overview Employees can link their LinkedIn accounts to automatically post scheduled content directly to LinkedIn, eliminating manual copy-paste work. ## Prerequisites 1. A LinkedIn Developer account 2. Access to your server's environment variables 3. HTTPS domain (required for OAuth) ## Step 1: Create LinkedIn App 1. Go to [LinkedIn Developers](https://www.linkedin.com/developers/apps) 2. Click "Create app" 3. Fill in app details: - **App name**: Your app name (e.g., "LinkedInWorkflow Auto-Poster") - **LinkedIn Page**: Select your company page - **App logo**: Upload a logo (optional) 4. Check the agreement and create the app ## Step 2: Configure OAuth Settings 1. In your app dashboard, go to the **Auth** tab 2. Add OAuth 2.0 redirect URLs: ``` https://yourdomain.com/settings/linkedin/callback ``` 3. Request the following **OAuth 2.0 scopes**: - `openid` - For user identity - `profile` - For user profile data - `email` - For user email - `w_member_social` - **CRITICAL** - For posting on user's behalf Note: `w_member_social` requires app review by LinkedIn. Submit for review if not already approved. 4. Note your **Client ID** and **Client Secret** (found in Auth tab) ## Step 3: Generate Encryption Key Run the helper script to generate a secure encryption key: ```bash python scripts/generate_encryption_key.py ``` Copy the generated key for the next step. ## Step 4: Configure Environment Variables Add these variables to your `.env` file: ```env # LinkedIn API (Custom OAuth for auto-posting) LINKEDIN_CLIENT_ID=your_client_id_here LINKEDIN_CLIENT_SECRET=your_client_secret_here LINKEDIN_REDIRECT_URI=https://yourdomain.com/settings/linkedin/callback # Token Encryption ENCRYPTION_KEY=your_generated_fernet_key_here ``` ⚠️ **Security**: Never commit these values to git! Keep them secure. ## Step 5: Run Database Migration Apply the database migration to create the `linkedin_accounts` table: ```bash # Using psql psql $DATABASE_URL -f config/migrate_add_linkedin_accounts.sql # Or via Supabase dashboard SQL editor # Copy and paste the contents of config/migrate_add_linkedin_accounts.sql ``` ## Step 6: Install Dependencies Install the new dependencies: ```bash pip install -r requirements.txt ``` ## Step 7: Restart Application Restart your application to load the new environment variables: ```bash # If using systemd sudo systemctl restart linkedinworkflow # If using docker docker-compose restart # If running directly # Stop the current process and restart ``` ## Step 8: Test the Integration 1. Log in as an employee user 2. Go to **Settings** (`/settings`) 3. Click **"Mit LinkedIn verbinden"** 4. Complete the LinkedIn OAuth flow 5. Verify the account shows as connected 6. Schedule a test post 7. Wait for the scheduled time (or manually trigger the scheduler) 8. Verify the post appears on LinkedIn ## Troubleshooting ### OAuth Errors **"Invalid redirect_uri"** - Make sure the redirect URI in your .env matches exactly with the one configured in LinkedIn app settings - Include the protocol (`https://`) and no trailing slash **"Insufficient permissions"** - Ensure `w_member_social` scope is requested and approved - Some scopes require LinkedIn app review ### Token Errors **"Token expired"** - LinkedIn tokens typically last 60 days - The system will attempt to refresh automatically - If refresh fails, user needs to reconnect **"Encryption error"** - Verify `ENCRYPTION_KEY` is set in environment - Never change the encryption key after storing tokens (or all tokens become unreadable) ### Posting Errors **"Rate limit exceeded"** - LinkedIn has rate limits on posting - The system will fall back to email notification - Wait before retrying **"Image upload failed"** - Check that the image URL is publicly accessible - Supabase storage URLs must be publicly readable - System will post without image if upload fails ## Rate Limits LinkedIn API has the following rate limits (as of 2024): - **Posts**: ~100 per day per user - **API calls**: Varies by endpoint Plan your posting schedule accordingly. ## Security Best Practices 1. **Never log tokens**: Tokens are encrypted at rest and should never be logged in plaintext 2. **HTTPS only**: OAuth requires HTTPS in production 3. **Secure cookies**: Session cookies use httponly, secure, and samesite flags 4. **Token rotation**: Encourage users to reconnect periodically 5. **Audit logging**: Monitor for suspicious activity in `linkedin_accounts.last_error` ## Architecture ``` ┌─────────────────┐ │ Employee │ │ (Settings Page) │ └────────┬────────┘ │ 1. OAuth Flow ▼ ┌─────────────────────────┐ │ linkedin_accounts table │ │ (encrypted tokens) │ └────────┬────────────────┘ │ 2. Scheduler checks ▼ ┌─────────────────────────┐ │ LinkedIn API Service │ │ (UGC Posts API) │ └─────────────────────────┘ ``` ## Monitoring Key metrics to monitor: - **Token expiry**: Check `linkedin_accounts.token_expires_at` - **API errors**: Check `linkedin_accounts.last_error` - **Success rate**: Compare scheduled posts vs. published posts - **Fallback rate**: How often email fallback is used Query to check accounts needing attention: ```sql SELECT user_id, linkedin_name, last_error, last_error_at, token_expires_at FROM linkedin_accounts WHERE (last_error IS NOT NULL OR token_expires_at < NOW() + INTERVAL '7 days') AND is_active = true; ``` ## Support For issues or questions: 1. Check logs for detailed error messages 2. Review LinkedIn API documentation 3. Verify environment configuration 4. Test with a single user account first