Skip to main content

Auth Service

๐Ÿ”€ Integration Pointsโ€‹

Internal Servicesโ€‹

  • Campaigns Service:

    • Campaign cleanup on disconnection
    • Soft delete facebook_ads campaigns
    • Preserves historical lead data
  • Facebook Provider (link removed - file does not exist):

    • getAccessToken() - Exchange auth code for token
    • getAppAccessToken() - Get app-level token
    • Token refresh logic (in provider)

External Servicesโ€‹

  • Facebook OAuth 2.0:
    • Authorization endpoint: /dialog/oauth
    • Token exchange endpoint
    • Refresh token endpoint
    • Permissions: leads_retrieval, ads_management, etc.

Utilitiesโ€‹

  • JWT (jsonwebtoken):

    • State token generation for CSRF protection
    • HS256 algorithm with APP_SECRET
    • Encodes account_id and forward_url
  • Query String Parser:

    • Parses JWT payload data
    • Extracts account_id and forward_url

๐Ÿงช Edge Cases & Special Handlingโ€‹

Sub-Account Validation Edge Casesโ€‹

Invalid Sub-Account ID:

// Sub-account doesn't exist or not owned by parent
if (!isValidSubAccount) {
return res.status(400).json({
message: 'Invalid SubAccount Id',
});
}

Sub-Account Without Parent Relationship:

// Query checks parent_account field
{
_id: subAccountId,
parent_account: parentAccountId
}
// Missing or wrong parent_account = validation fails

Token Management Edge Casesโ€‹

Token Already Exists:

  • loginAuth: Returns existing token immediately
  • postApiKey: Checks for race condition, returns existing

Token Invalidated Manually:

if (existKeys.token_invalidated == true) {
// Delete and force re-authentication
await keysModel.deleteAll(accountId);
}

Token Expiration Buffer:

// 10-minute buffer before actual expiration
expires_in = original_expires_in - 600 + current_timestamp;
// Ensures refresh happens before token actually expires

OAuth Callback Edge Casesโ€‹

Invalid JWT State:

try {
payload = jwt.verify(state, APP_SECRET);
} catch (error) {
return res.status(401).json({ message: 'Invalid State' });
}
// Prevents CSRF attacks and replay attacks

Missing Authorization Code:

// If user denies permissions
// Facebook redirects without code parameter
// Function should handle missing code gracefully

Multiple Simultaneous OAuth Flows:

// User clicks "Connect" multiple times
// Race condition: Multiple OAuth flows in parallel
// postApiKey checks for existing token before saving
const searchRecord = await keysModel.find(null, accountId);
if (searchRecord) {
// Return existing token instead of creating duplicate
}

Disconnection Edge Casesโ€‹

Partial Disconnect with Active Campaigns:

// global=false and campaigns exist
// Only delete analytics config, preserve tokens
// Campaigns continue receiving leads

Global Disconnect Soft Deletes:

// Campaigns soft-deleted (is_deleted: true)
// Preserves historical leads and analytics
// Can be restored if needed

No Campaigns or Config:

// Disconnect when nothing connected
// No-op: Just return success
// Prevents errors on already-disconnected accounts

โš ๏ธ Important Notesโ€‹

  1. Sub-Account Support: Parent accounts can connect Facebook for sub-accounts. Always validate parent_account relationship before allowing sub-account operations. Invalid sub-accounts return 400 error.

  2. Token Reuse: loginAuth returns existing tokens if valid. Prevents unnecessary re-authentication. Check token_invalidated flag before reusing tokens.

  3. CSRF Protection: JWT state token prevents CSRF attacks in OAuth flow. Always verify state parameter on callback. Invalid state returns 401 error.

  4. Token Expiration Buffer: 10-minute buffer subtracted from Facebook's expires_in. Ensures proactive token refresh before actual expiration. Stored as absolute timestamp (not relative).

  5. Race Condition Handling: postApiKey checks for existing tokens before saving. Handles users clicking "Connect" multiple times. Returns existing token instead of creating duplicate.

  6. Comprehensive Scopes: OAuth requests 10+ permissions including leads_retrieval (critical). Missing scopes cause webhook failures. Always use full scope list.

  7. Global vs Partial Disconnect: global=true soft deletes all campaigns and hard deletes tokens. global=false preserves tokens if campaigns exist. Choose based on intent (full disconnect vs analytics-only disconnect).

  8. Campaign Preservation: Soft delete (is_deleted: true) maintains historical lead data. Hard delete would lose all captured leads. Never hard delete campaigns with leads.

  9. Forward URL Required: loginAuth requires forward_url for redirect after auth. Missing forward_url returns 400 error. URL must be whitelisted in Facebook App settings.

  10. Token Security: Tokens stored in database, only document ID returned to client. Never expose access_token or refresh_token to client. Use token ID for API calls.

  • Campaigns Service - Campaign management and cleanup
  • Webhooks Service - Uses tokens for Facebook Lead Ads
  • Facebook Provider (link removed - file does not exist) - Facebook API integration
  • Analytics Facebook Ads (link removed - file does not exist) - Uses ad account config
  • OAuth 2.0 Specification - OAuth protocol details
๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM