Skip to content

Authentication

Sairo uses JWT-based authentication with secure cookie storage. Tokens are issued on login and validated on every API request.

Sairo supports two authentication modes, controlled by the AUTH_MODE environment variable:

ModeAUTH_MODELogin FieldsBest For
Local (default)localUsername + PasswordTeams with multiple users, RBAC, 2FA
S3 Keyss3S3 Access Key + Secret KeySingle-user setups, quick start, headless

In S3 mode, users authenticate by entering their S3 access key and secret key. Sairo validates the credentials by calling list_buckets() against the configured S3 endpoint. If it succeeds, the user gets an admin session. No user account setup needed.

environment:
AUTH_MODE: "s3" # Authenticate with S3 credentials instead of username/password

Both modes can be used simultaneously — the login page shows a toggle to switch between “S3 Keys” and “Password”. In s3 mode, the S3 tab is shown first. In local mode, the password tab is shown first (S3 tab appears only if explicitly enabled).

When a user logs in, the backend issues a signed JWT and sets it as an httpOnly cookie with SameSite=Strict. This prevents JavaScript from reading the token and blocks the cookie on all cross-site navigations.

Every subsequent request includes the cookie automatically. The backend validates the token signature, checks expiration, and extracts the user identity.

Sessions last 24 hours by default. You can change this with the SESSION_HOURS environment variable:

environment:
SESSION_HOURS: "48" # 48-hour sessions

Five minutes before a session expires, a toast notification appears in the UI with an Extend button. Clicking it issues a fresh token without requiring re-login.

If the session expires without extension, the user is redirected to the login page.

The SECURE_COOKIE environment variable controls whether the cookie is sent only over HTTPS:

DeploymentSECURE_COOKIE
Behind HTTPS reverse proxytrue (recommended)
Plain HTTP (local/dev)false
environment:
SECURE_COOKIE: "true"

If SECURE_COOKIE=true but you access Sairo over plain HTTP, the browser will not send the cookie and login will appear broken. Set it to false for HTTP deployments.

Login attempts are rate-limited with two layers:

  • 10 requests per minute via the global rate limiter (applied to the login endpoint)
  • 10 requests per 5 minutes per IP address via a hardcoded per-IP window

Both limits apply simultaneously. After exceeding either limit, the API returns 429 Too Many Requests until the window resets. These limits are not independently configurable.

All passwords are hashed with bcrypt before storage. Plaintext passwords are never written to disk or logs. Passwords must be at least 8 characters long.

On first startup, Sairo auto-generates:

  • A JWT_SECRET used to sign tokens (generated in-memory if not set via env var)
  • An admin account with the username and password from ADMIN_USER and ADMIN_PASS environment variables

If JWT_SECRET is not explicitly set, a random secret is generated in memory on each startup. This means all active sessions are invalidated on restart. For production and multi-instance deployments, always set JWT_SECRET explicitly.

environment:
ADMIN_USER: "admin"
ADMIN_PASS: "your-secure-password"
JWT_SECRET: "a-long-random-string"