Auth Service
๐ Integration Pointsโ
Internal Servicesโ
-
- 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 tokengetAppAccessToken()- 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.
- Authorization endpoint:
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โ
-
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.
-
Token Reuse: loginAuth returns existing tokens if valid. Prevents unnecessary re-authentication. Check token_invalidated flag before reusing tokens.
-
CSRF Protection: JWT state token prevents CSRF attacks in OAuth flow. Always verify state parameter on callback. Invalid state returns 401 error.
-
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).
-
Race Condition Handling: postApiKey checks for existing tokens before saving. Handles users clicking "Connect" multiple times. Returns existing token instead of creating duplicate.
-
Comprehensive Scopes: OAuth requests 10+ permissions including leads_retrieval (critical). Missing scopes cause webhook failures. Always use full scope list.
-
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).
-
Campaign Preservation: Soft delete (is_deleted: true) maintains historical lead data. Hard delete would lose all captured leads. Never hard delete campaigns with leads.
-
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.
-
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.
๐ Related Documentationโ
- 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