Authentication Guide
Overview
The FF Messaging Service implements a robust authentication system using JWT (JSON Web Tokens) combined with session-based authentication. This guide covers the authentication process, token management, and security best practices.
Authentication Flow
- User provides authentication credentials (authid, sessid)
- Service validates credentials against the authentication service
- Upon successful validation, a JWT token is issued
- All subsequent requests must include the JWT token and session identifiers
Required Headers
All authenticated requests must include:
Authorization: Bearer <jwt_token>
authid: <authentication_id>
sid: <session_id>
Authentication Process
1. WebSocket Authentication
socket.emit("register_user", {
authid: "e26f8340-a635-4974-9074-eb380245e053",
sessid: "08c1ddd0-d9d4-4c9c-9d26-caf2cdd58d92"
});
The service will:
- Validate the authid and sessid combination
- Retrieve the associated user ID
- Register the socket connection for that user
- Return success/failure response
2. REST Authentication
For REST endpoints, include the authentication headers with every request:
const headers = {
'Authorization': 'Bearer your-jwt-token',
'authid': 'your-auth-id',
'sid': 'your-session-id'
};
fetch('/api/messages', {
method: 'POST',
headers: headers,
body: JSON.stringify(message)
});
Security Measures
Token Expiration
- JWTs expire after a configured period
- Expired tokens require re-authentication
- Session validity is checked on each request
Session Management
- Each user can have multiple active sessions
- Sessions are tracked in Redis
- Stale sessions are automatically cleaned up
Rate Limiting
- Enforced on authentication endpoints
- Configurable limits per time window
- Prevents brute force attempts
Error Handling
Invalid Authentication
{
"status": 401,
"data": {
"error": "Invalid authentication credentials"
}
}
Expired Token
{
"status": 401,
"data": {
"error": "The token has expired"
}
}
Missing Token
{
"status": 401,
"data": {
"error": "Request does not contain an access token"
}
}
Organization Authentication
When authenticating for organization access:
socket.emit("register_organization", {
authid: "user-auth-id",
sessid: "session-id",
from_oid: organization_id
});
The service validates:
- User authentication
- User's association with the organization
- Organization's existence and status
Implementation Examples
Authentication Setup
# Server-side configuration
JWT_SECRET_KEY = config('JWT_SECRET_KEY', default='jwt-secret-string')
jwt = JWTManager(app)
@jwt.expired_token_loader
def expired_token_callback(jwt_header, jwt_payload):
return jsonify({"error": "Token has expired"}), 401
@jwt.invalid_token_loader
def invalid_token_callback(error):
return jsonify({"error": "Invalid token"}), 422
Client-side Implementation
class AuthService {
constructor() {
this.token = null;
this.authid = null;
this.sid = null;
}
async authenticate(credentials) {
try {
const response = await fetch('/api/auth', {
method: 'POST',
body: JSON.stringify(credentials)
});
const data = await response.json();
if (data.status === 200) {
this.token = data.data.token;
this.authid = credentials.authid;
this.sid = data.data.sid;
return true;
}
return false;
} catch (error) {
console.error('Authentication failed:', error);
return false;
}
}
getHeaders() {
return {
'Authorization': `Bearer ${this.token}`,
'authid': this.authid,
'sid': this.sid
};
}
isAuthenticated() {
return !!this.token;
}
}
Best Practices
-
Token Management
- Store tokens securely
- Implement token refresh mechanism
- Clear tokens on logout
-
Error Handling
- Implement proper error handling
- Provide clear error messages
- Log authentication failures
-
Security
- Use HTTPS for all requests
- Implement rate limiting
- Validate all inputs
-
Session Management
- Track active sessions
- Implement session timeout
- Allow multiple device sessions
-
Organization Access
- Validate organization membership
- Implement role-based access
- Track organization-level permissions