Security
Security Features
The Infomaxim API implements comprehensive security measures to protect your data and ensure safe operation.
Authentication & Authorization
- JWT Tokens: Secure authentication using JSON Web Tokens with separate access and refresh tokens
- Token Expiration: Access tokens expire after 1 hour, refresh tokens after 30 days
- Password Hashing: bcrypt with 12 salt rounds for secure password storage
- Role-Based Access: Admin and user roles with permission-based endpoint access
Data Protection
- SQL Injection Prevention: Parameterized queries and secure WHERE clause validation
- Input Validation: Joi schema validation on all input parameters
- Encryption: AES-256 encryption for sensitive data at rest
- HTTPS Required: All production endpoints require secure HTTPS connections
Security Headers
The API automatically applies security headers via Helmet.js:
- Content-Security-Policy: XSS protection
- X-Frame-Options: Clickjacking protection
- X-Content-Type-Options: MIME type sniffing protection
- Strict-Transport-Security: Force HTTPS connections
CORS Configuration
Cross-Origin Resource Sharing is configured with origin validation. Configure allowed origins in your environment:
FRONTEND_DOMAIN=https://yourdomain.com
Rate Limiting
The API implements rate limiting to prevent abuse and ensure fair usage across all clients.
Rate Limit Configuration
| Parameter | Value |
|---|---|
| Requests per IP | 100 requests |
| Time Window | 15 minutes |
| Excluded Endpoints | /health, /status |
Rate Limit Headers
Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704110400
Rate Limit Exceeded Response
When rate limit is exceeded, the API returns a 429 status code:
{
"status": "Failed",
"message": "Too many requests, please try again later",
"retryAfter": 600
}
IP Address Detection
The rate limiter uses the following priority for IP detection:
req.ip- Express-parsed IP (configured with trust proxy)x-forwarded-forheader - For requests through proxiesreq.socket.remoteAddress- Direct connection IP
x-forwarded-for header to accurately track client IPs.
Customizing Rate Limits
Configure rate limits via environment variables:
# .env file
RATE_LIMIT_WINDOW_MS=900000 # 15 minutes in milliseconds
RATE_LIMIT_MAX_REQUESTS=100 # Max requests per window
Error Handling
The API implements comprehensive error handling with detailed error responses and logging.
Error Response Format
{
"status": "Failed",
"message": "Detailed error message",
"errors": [
{
"field": "email",
"message": "Invalid email format"
},
{
"field": "password",
"message": "Password must be at least 8 characters"
}
],
"errorType": "ValidationError",
"errorCode": "ERR_VALIDATION_FAILED"
}
Error Types
| Error Type | Description | Status Code |
|---|---|---|
| AuthenticationError | Invalid or missing authentication | 401 |
| AuthorizationError | Insufficient permissions | 403 |
| ValidationError | Invalid input parameters | 400 |
| NotFoundError | Resource not found | 404 |
| ConflictError | Resource already exists | 409 |
| DatabaseError | Database operation failed | 500 |
| NetworkError | External service unavailable | 503 |
| RateLimitError | Rate limit exceeded | 429 |
Error Logging
All errors are logged with context information for debugging:
- Error Details: Type, message, and stack trace
- Request Context: URL, method, headers, and body
- User Context: User ID and session information
- Timestamp: ISO 8601 formatted timestamp
Retry Mechanisms
For transient errors (network, database connection), the API implements:
- Automatic Retry: Up to 3 retries with exponential backoff
- Circuit Breaker: Prevents cascading failures for external services
- Graceful Degradation: Returns cached data when possible
Client-Side Error Handling
Recommended error handling pattern for API clients:
// JavaScript Example
async function callAPI() {
try {
const response = await fetch('http://localhost:3001/getDataRows', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
});
const data = await response.json();
if (data.status === 'Failed') {
// Handle API error
console.error('API Error:', data.message);
if (data.errors) {
data.errors.forEach(err => {
console.error(`Field ${err.field}: ${err.message}`);
});
}
return null;
}
return data.data;
} catch (error) {
// Handle network error
console.error('Network Error:', error);
return null;
}
}