Skip to main content

Authentication

User Authentication (is-auth.js)

JWT-based authentication with multiple token sources

Token Sources (Priority Order)

  1. session_id → Lookup in ApiSession collection
  2. token parameter → Direct JWT token
  3. Query string token → URL parameter
  4. x-token header → HTTP header

JWT Payload Structure

Decoded JWT Payload:

{
workspace_id: String, // Workspace identifier
account_id: String, // Account identifier
uid: String, // User ID
scope: String, // Space-separated permissions (e.g., "conversation analytics")
assignment: Object // User role assignments
}

Scope Conversion

Input/Output Example:

// Input: "conversation analytics crm"
// Output: ["conversation", "analytics", "crm"]

Authentication Flow

1. Client connects with token

2. Middleware extracts token from query/header

3. If session_id → Lookup ApiSession → Get JWT token

4. Verify JWT with JWT_SECRET

5. Parse scope string to array

6. Attach auth object to socket/request

7. Continue to event handler

Scope Verification (scope.js)

Purpose

Verify user has required permission scope before executing socket events

Implementation

const verifyScope = (data, allowedScopes) => {
try {
let allowed = false;
allowedScopes.forEach(s => {
if (data.auth.scope.includes(s)) allowed = true;
});
if (!allowed) {
return Promise.reject({ errno: 403, message: 'NOT_ENOUGH_SCOPE' });
}
return Promise.resolve();
} catch (error) {
return Promise.reject(error);
}
};

Usage Example

// In event handler
async onMessage(data, callback) {
try {
data = await isAuth(data);
await verifyScope(data, ['conversation']); // Require 'conversation' scope

// Handle message...
} catch (error) {
sendResponse(error, callback);
}
}

Connection-Level Verification

// Applied on namespace connection
io.use(isAuth)
.use(verifyScopeOnConnection(['conversation']))
.on('connect', this.onConnect.bind(this));

Visitor Authentication (is-auth-visitor.js)

Current Status: Development placeholder with hardcoded auth object

Note: This middleware currently returns a static auth object and should be reviewed for production readiness before use in production environments.


Authentication Examples

Socket.IO Client with Token

import io from 'socket.io-client';

const socket = io('http://localhost:4000/v1/conversation', {
transports: ['websocket'],
query: {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
},
});

Socket.IO Client with Session ID

const socket = io('http://localhost:4000/v1/conversation', {
transports: ['websocket'],
query: {
session_id: '64abc123def456789',
},
});

Socket.IO Client with Header

const socket = io('http://localhost:4000/v1/conversation', {
transports: ['websocket'],
extraHeaders: {
'x-token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
},
});

Security Best Practices

  1. Use HTTPS/WSS in Production: Always use secure connections
  2. Rotate JWT Secrets Regularly: Update JWT_SECRET periodically
  3. Implement Token Expiration: Set reasonable JWT expiration times
  4. Validate Token Claims: Always verify workspace_id and account_id
  5. Rate Limiting: Implement per-user rate limits for events
  6. IP Whitelisting: Consider IP restrictions for sensitive operations
💬

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