Skip to main content
Skip to main content
Version: 1.0 (Current)

Authentication

The x3Algo API uses JWT (JSON Web Tokens) for authentication. This guide covers all authentication endpoints and token management.

Authentication Flow

sequenceDiagram
participant Client
participant API
participant Database

Client->>API: POST /api/auth/login
API->>Database: Verify credentials
Database-->>API: User found
API-->>Client: Access token + Refresh token

Client->>API: GET /api/trading/algorithms
Note over Client,API: Authorization: Bearer <access_token>
API-->>Client: Algorithms data

Note over Client: Access token expires (15 min)

Client->>API: POST /api/auth/refresh-token
Note over Client,API: Refresh token in cookie
API-->>Client: New access token

Token Types

Access Token

  • Purpose: Authenticate API requests
  • Lifetime: 15 minutes
  • Storage: Memory or secure storage (not localStorage)
  • Format: JWT Bearer token

Refresh Token

  • Purpose: Obtain new access tokens
  • Lifetime: 7 days
  • Storage: HTTP-only, secure cookie
  • Format: JWT token

Signup

Register a new user account.

Endpoint

POST /api/auth/signup

Request

Headers:

Content-Type: application/json

Body:

{
"email": "user@example.com",
"password": "SecurePassword123!",
"name": "John Doe"
}

Parameters:

FieldTypeRequiredDescription
emailstringYesValid email address
passwordstringYesMinimum 8 characters
namestringYesUser's full name

Response

Success (201 Created):

{
"success": true,
"message": "User registered successfully. Please verify your email.",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"emailVerified": false,
"createdAt": "2024-01-15T10:30:00Z"
},
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900
}

Set-Cookie Header:

Set-Cookie: refreshToken=<token>; HttpOnly; Secure; SameSite=Strict; Max-Age=604800

Errors

StatusCodeMessage
400VALIDATION_ERRORInvalid email or password format
409CONFLICTEmail already registered
429TOO_MANY_REQUESTSRate limit exceeded (5 requests per 15 minutes)

Example

cURL:

curl -X POST https://api.x3algo.com/api/auth/signup \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123!",
"name": "John Doe"
}'

JavaScript:

const response = await fetch('https://api.x3algo.com/api/auth/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePassword123!',
name: 'John Doe'
})
})

const data = await response.json()
console.log('Access Token:', data.accessToken)

Python:

import requests

response = requests.post(
'https://api.x3algo.com/api/auth/signup',
json={
'email': 'user@example.com',
'password': 'SecurePassword123!',
'name': 'John Doe'
}
)

data = response.json()
print('Access Token:', data['accessToken'])

Login

Authenticate an existing user.

Endpoint

POST /api/auth/login

Request

Headers:

Content-Type: application/json

Body:

{
"email": "user@example.com",
"password": "SecurePassword123!"
}

Parameters:

FieldTypeRequiredDescription
emailstringYesUser's email address
passwordstringYesUser's password

Response

Success (200 OK):

{
"success": true,
"message": "Login successful",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"emailVerified": true,
"role": "user"
},
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900
}

Set-Cookie Header:

Set-Cookie: refreshToken=<token>; HttpOnly; Secure; SameSite=Strict; Max-Age=604800

Errors

StatusCodeMessage
400VALIDATION_ERROREmail and password are required
401UNAUTHORIZEDInvalid credentials
429TOO_MANY_REQUESTSRate limit exceeded (5 requests per 15 minutes)

Example

cURL:

curl -X POST https://api.x3algo.com/api/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "user@example.com",
"password": "SecurePassword123!"
}'

JavaScript:

const response = await fetch('https://api.x3algo.com/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include', // Important: Include cookies
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePassword123!'
})
})

const data = await response.json()
localStorage.setItem('accessToken', data.accessToken) // Store in memory instead

Python:

import requests

session = requests.Session()

response = session.post(
'https://api.x3algo.com/api/auth/login',
json={
'email': 'user@example.com',
'password': 'SecurePassword123!'
}
)

data = response.json()
access_token = data['accessToken']

Refresh Token

Obtain a new access token using the refresh token.

Endpoint

POST /api/auth/refresh-token

Request

Headers:

Cookie: refreshToken=<refresh_token>

No request body required. The refresh token is automatically sent via HTTP-only cookie.

Response

Success (200 OK):

{
"success": true,
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900
}

Errors

StatusCodeMessage
401UNAUTHORIZEDInvalid or expired refresh token
401UNAUTHORIZEDRefresh token not found

Example

cURL:

curl -X POST https://api.x3algo.com/api/auth/refresh-token \
-b cookies.txt \
-c cookies.txt

JavaScript:

const response = await fetch('https://api.x3algo.com/api/auth/refresh-token', {
method: 'POST',
credentials: 'include' // Include cookies
})

const data = await response.json()
// Update access token in memory
updateAccessToken(data.accessToken)

Python:

response = session.post(
'https://api.x3algo.com/api/auth/refresh-token'
)

data = response.json()
access_token = data['accessToken']

Logout

Invalidate the current session and refresh token.

Endpoint

POST /api/auth/logout

Request

Headers:

Authorization: Bearer <access_token>
Cookie: refreshToken=<refresh_token>

No request body required.

Response

Success (200 OK):

{
"success": true,
"message": "Logout successful"
}

Set-Cookie Header:

Set-Cookie: refreshToken=; HttpOnly; Secure; SameSite=Strict; Max-Age=0

Example

cURL:

curl -X POST https://api.x3algo.com/api/auth/logout \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-b cookies.txt

JavaScript:

await fetch('https://api.x3algo.com/api/auth/logout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`
},
credentials: 'include'
})

// Clear access token from memory
clearAccessToken()

Using Access Tokens

Include the access token in the Authorization header for all authenticated requests:

GET /api/trading/algorithms
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Example

cURL:

curl -X GET https://api.x3algo.com/api/trading/algorithms \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

JavaScript:

const response = await fetch('https://api.x3algo.com/api/trading/algorithms', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
})

Python:

headers = {
'Authorization': f'Bearer {access_token}'
}

response = requests.get(
'https://api.x3algo.com/api/trading/algorithms',
headers=headers
)

Token Refresh Strategy

Implement automatic token refresh to maintain seamless user experience:

JavaScript Example

let accessToken = null
let refreshPromise = null

async function refreshAccessToken() {
// Prevent multiple simultaneous refresh requests
if (refreshPromise) return refreshPromise

refreshPromise = fetch('https://api.x3algo.com/api/auth/refresh-token', {
method: 'POST',
credentials: 'include'
})
.then(res => res.json())
.then(data => {
accessToken = data.accessToken
refreshPromise = null
return accessToken
})
.catch(error => {
refreshPromise = null
// Redirect to login if refresh fails
window.location.href = '/login'
throw error
})

return refreshPromise
}

async function apiRequest(url, options = {}) {
// Add access token to request
options.headers = {
...options.headers,
'Authorization': `Bearer ${accessToken}`
}

let response = await fetch(url, options)

// If 401, try to refresh token and retry
if (response.status === 401) {
await refreshAccessToken()

// Retry request with new token
options.headers['Authorization'] = `Bearer ${accessToken}`
response = await fetch(url, options)
}

return response
}

// Usage
const algorithms = await apiRequest('https://api.x3algo.com/api/trading/algorithms')

Python Example

import requests
from datetime import datetime, timedelta

class APIClient:
def __init__(self):
self.session = requests.Session()
self.access_token = None
self.token_expires_at = None

def login(self, email, password):
response = self.session.post(
'https://api.x3algo.com/api/auth/login',
json={'email': email, 'password': password}
)
data = response.json()
self.access_token = data['accessToken']
self.token_expires_at = datetime.now() + timedelta(seconds=data['expiresIn'])

def refresh_token(self):
response = self.session.post(
'https://api.x3algo.com/api/auth/refresh-token'
)
data = response.json()
self.access_token = data['accessToken']
self.token_expires_at = datetime.now() + timedelta(seconds=data['expiresIn'])

def request(self, method, url, **kwargs):
# Refresh token if expired or about to expire
if not self.access_token or datetime.now() >= self.token_expires_at - timedelta(minutes=1):
self.refresh_token()

# Add authorization header
headers = kwargs.get('headers', {})
headers['Authorization'] = f'Bearer {self.access_token}'
kwargs['headers'] = headers

response = self.session.request(method, url, **kwargs)

# Retry with refresh if 401
if response.status_code == 401:
self.refresh_token()
headers['Authorization'] = f'Bearer {self.access_token}'
response = self.session.request(method, url, **kwargs)

return response

# Usage
client = APIClient()
client.login('user@example.com', 'password')

algorithms = client.request('GET', 'https://api.x3algo.com/api/trading/algorithms')

Security Best Practices

1. Store Tokens Securely

❌ Don't:

// Never store tokens in localStorage (vulnerable to XSS)
localStorage.setItem('accessToken', token)

✅ Do:

// Store in memory (React state, closure, etc.)
let accessToken = null

function setAccessToken(token) {
accessToken = token
}

// Or use secure, HTTP-only cookies (handled by server)

2. Use HTTPS

Always use HTTPS in production to prevent token interception:

// ✅ Production
const API_URL = 'https://api.x3algo.com'

// ⚠️ Development only
const API_URL = 'http://localhost:8000'

3. Handle Token Expiration

Implement automatic token refresh before expiration:

// Refresh token 1 minute before expiration
const REFRESH_BUFFER = 60 * 1000 // 1 minute

function scheduleTokenRefresh(expiresIn) {
const refreshTime = (expiresIn * 1000) - REFRESH_BUFFER
setTimeout(refreshAccessToken, refreshTime)
}

4. Clear Tokens on Logout

Always clear tokens when user logs out:

async function logout() {
await fetch('https://api.x3algo.com/api/auth/logout', {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
credentials: 'include'
})

// Clear access token from memory
accessToken = null

// Redirect to login
window.location.href = '/login'
}

5. Validate Tokens

Never trust client-side token validation. Always validate on the server:

// ❌ Don't decode and trust JWT on client
const decoded = jwt.decode(accessToken)
if (decoded.role === 'admin') {
// Show admin features
}

// ✅ Do: Let server validate and return user info
const response = await fetch('https://api.x3algo.com/api/auth/profile', {
headers: { 'Authorization': `Bearer ${accessToken}` }
})
const user = await response.json()
if (user.role === 'admin') {
// Show admin features
}

Troubleshooting

Token Expired

Error:

{
"error": {
"message": "Token expired",
"code": "UNAUTHORIZED",
"status": 401
}
}

Solution: Use the refresh token endpoint to obtain a new access token.

Invalid Token

Error:

{
"error": {
"message": "Invalid token",
"code": "UNAUTHORIZED",
"status": 401
}
}

Solution: Token may be malformed or tampered with. Re-authenticate the user.

Refresh Token Expired

Error:

{
"error": {
"message": "Refresh token expired",
"code": "UNAUTHORIZED",
"status": 401
}
}

Solution: Refresh token has expired (7 days). User must log in again.

Rate Limit Exceeded

Error:

{
"error": {
"message": "Too many login attempts",
"code": "TOO_MANY_REQUESTS",
"status": 429,
"retryAfter": 900
}
}

Solution: Wait for the specified time (in seconds) before retrying.