perform.chat
Auth for Chat

Security Best Practices

Keep your implementation secure

Do's

  1. Generate tokens server-side - Never expose API credentials in frontend code
  2. Use HTTPS - Always use secure connections in production
  3. Store customer user IDs - Save user.id from token generation for invalidation
  4. Use shorter expiration times - Set expiresIn to 15m-1h for high-security scenarios
  5. Invalidate on security events - Always invalidate tokens after password resets, permission changes, or suspicious activity
  6. Store tokens securely - Use httpOnly cookies or secure session storage
  7. Validate users - Ensure users are authenticated in YOUR system before generating tokens
  8. Set appropriate permissions - Only grant permissions your users actually need
  9. Monitor token usage - Track API key usage and invalidation attempts for anomalies
  10. Rotate API keys - Periodically rotate your API keys
  11. Use environment variables - Store credentials in environment variables, not code

Don'ts

  1. Never expose keySecret - Don't include it in frontend code, logs, or repositories
  2. Don't reuse tokens - Generate fresh tokens for each session
  3. Don't hardcode credentials - Use environment variables or secure vaults
  4. Don't skip authentication - Always verify users in your system first
  5. Don't share tokens between users - Each user should have their own token
  6. Don't log tokens - Tokens in logs are a security risk
  7. Don't use test tokens in production - Test endpoint is for development only
  8. Don't use long expiration times unnecessarily - Default 24h is reasonable, avoid 7d+ unless required

Token Lifecycle

sequenceDiagram participant User participant YourApp participant YourBackend participant PerformChat User->>YourApp: Opens chat widget YourApp->>YourBackend: Request chat token YourBackend->>YourBackend: Verify user authentication YourBackend->>PerformChat: POST /rest/v1/auth/token PerformChat->>PerformChat: Validate API key PerformChat->>PerformChat: Find/create customer_user PerformChat->>PerformChat: Generate JWT token PerformChat-->>YourBackend: Return token YourBackend-->>YourApp: Return token YourApp->>PerformChat: Connect with token PerformChat->>PerformChat: Verify token PerformChat-->>YourApp: Connection established Note over User,PerformChat: Token expires after expiresIn period (default: 24h) User->>YourApp: Continues chatting YourApp->>PerformChat: Token expired PerformChat-->>YourApp: 401 Unauthorized YourApp->>YourBackend: Request new token YourBackend->>PerformChat: POST /rest/v1/auth/token PerformChat-->>YourBackend: New token YourBackend-->>YourApp: New token YourApp->>PerformChat: Reconnect with new token

Token Validation Process

When a request is made with a JWT token, the following checks are performed:

  1. JWT signature is valid - Cryptographic verification
  2. JWT has not expired - Check expiresIn timestamp
  3. Customer user exists and is active - Database lookup
  4. Token version matches - payload.tokenVersion === customer_user.token_version
  5. User belongs to correct company - Company isolation
  6. Agent is active - Agent status check

If any check fails → 401 Unauthorized

Token Invalidation Strategies

When to Invalidate

Always invalidate tokens in these scenarios:

  1. Password Reset - User changes password
  2. Permission Changes - User role or permissions modified
  3. Account Compromise - Suspicious activity detected
  4. Logout All Devices - User requests to logout everywhere
  5. Account Deletion - User account is deleted or deactivated

Example: Invalidation After Password Reset

// After successful password reset
await updateUserPassword(userId, newPassword)

// Invalidate all existing tokens
await fetch('/auth/invalidate-token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    keyId: process.env.API_KEY_ID,
    keySecret: process.env.API_KEY_SECRET,
    customerUserId: user.performChatUserId
  })
})

// User must login again with new password

Token Expiration Best Practices

Use CaseRecommended expiresInReason
High-security operations15m - 30mMinimize exposure window
Standard chat sessions1h - 4hBalance security and UX
Long-running integrations24h (default)Reasonable default
Trusted environments only7dUse sparingly

Storage Recommendations

Secure Storage

// Store in your database
await db.users.update({
  where: { id: userId },
  data: {
    performChatToken: token,
    performChatUserId: customerUserId, // For invalidation
    performChatTokenExpiry: expiresAt
  }
})

// Client-side: httpOnly cookie (preferred)
res.cookie('chat_token', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 24 * 60 * 60 * 1000 // 24 hours
})

Insecure Storage

// Never do this
localStorage.setItem('token', token) // Vulnerable to XSS
sessionStorage.setItem('token', token) // Still vulnerable
window.chatToken = token // Exposed globally

Monitoring & Alerts

Set up monitoring for:

  1. Failed token validation attempts - Possible attack
  2. Unusual invalidation patterns - Multiple invalidations in short time
  3. Token generation spikes - Unusual activity
  4. Expired token usage - Users with expired tokens