Skip to content

Authentication

LogSys uses JWT access + refresh tokens. The backend sets tokens in HttpOnly cookies (XSS-safe) and also returns them in the JSON body for CLI/test clients.


Token Model

Token Cookie Lifetime Purpose
Access ACCESS_TOKEN access_token_expire_minutes (default 60 min) Authorize every request / WS
Refresh REFRESH_TOKEN refresh_token_expire_days (default 7 days) Obtain new access token

Cookie flags

Flag Value Why
HttpOnly true JS (document.cookie) cannot read them → XSS-safe
Secure cookie_secure (false in dev) Only over HTTPS in production
SameSite cookie_samesite (Strict) CSRF protection

Endpoints

Method Path Description
POST /api/auth/login Authenticate with email + password
POST /api/auth/refresh Rotate access token with a valid refresh token
POST /api/auth/logout Clear auth cookies (204)
GET /api/auth/me Current user profile

Login

POST /api/auth/login
Content-Type: application/json
{ "email": "admin@dxc.com", "password": "…" }

Response 200 — sets cookies AND returns tokens:

{
  "access_token": "eyJhbGciOi…",
  "refresh_token": "eyJhbGciOi…"
}

Errors

Code HTTP When
invalid_credentials 401 Wrong email/password
account_disabled 403 User is inactive

Rate limited by login_limit.


Refresh

POST /api/auth/refresh
{ "refresh_token": "eyJhbGciOi…" }

Rotates to a new access token + new refresh token (sets cookies). Validates type == "refresh" and that the user is still active.

Errors

Code HTTP When
invalid_refresh_token 401 Token invalid or not a refresh token
invalid_user 401 User missing or inactive

Logout

POST /api/auth/logout

Deletes both auth cookies. Returns 204. The client should also clear local state.


Current User

GET /api/auth/me
Authorization: Bearer <access_token>
{
  "id": "3f3d2d5a-…",
  "email": "admin@dxc.com",
  "role": "superadmin",
  "is_active": true
}

How to Authenticate

Login once; the browser stores HttpOnly cookies and sends them automatically on every request and WebSocket connection.

Capture the access token from the login body and send it as a Bearer header:

TOKEN=$(curl -s -X POST localhost:8000/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@dxc.com","password":"…"}' | jq -r .access_token)

curl -s localhost:8000/api/kpis -H "Authorization: Bearer $TOKEN"

The WS endpoint accepts the token via four methods (in order): Authorization: Bearer, Sec-WebSocket-Protocol: jwt.<token>, the ACCESS_TOKEN cookie, then ?token= query. See WebSocket.


Roles (RBAC)

Role Access
viewer Read-only dashboards, logs, KPIs
manager Manage alerts, incidents, source toggles
admin All the above + users, tasks, clear-all
superadmin Everything including user roles

Each router declares the page permission it requires (e.g. require_page("sources")); require_roles("admin", "superadmin") guards destructive actions.


Security Notes

  • Never read tokens from document.cookie in the frontend (HttpOnly makes it impossible anyway).
  • cookie_secure must be true in production.
  • Store hashed passwords only (verify_password against bcrypt hash).
  • Tokens encode sub (user UUID) and role; role changes require re-login.