AllureDeck's security features are disabled by default for ease of local development. Set SECURITY_ENABLED=true (or SECURITY_ENABLED=1) to enable authentication and authorization.
AllureDeck uses JWT (JSON Web Tokens) for stateless authentication.
- Access token — short-lived (default 15 min / 900s), contains username and role claim. Delivered as
jwtcookie orAuthorization: Bearerheader. - Refresh token — long-lived (default 30 days / 2592000s). Delivered as
refresh_jwtcookie. Used to obtain new access tokens without re-login.
- Algorithm: HMAC-SHA256 (
HS256) - Key:
JWT_SECRET_KEYenv var
Production requirement: The API refuses to start if SECURITY_ENABLED=true and JWT_SECRET_KEY is still the default value (super-secret-key-for-dev). Generate a strong key:
openssl rand -hex 32- Every token carries a unique JTI (JWT ID).
- Revoked JTIs are persisted to a
jwt_blacklisttable in SQLite and survive restarts. - A background goroutine periodically prunes expired blacklist entries.
Configure via env vars or YAML:
| Setting | Variable | Default |
|---|---|---|
| Access token TTL | JWT_ACCESS_TOKEN_EXPIRES |
900 (15 min) |
| Refresh token TTL | JWT_REFRESH_TOKEN_EXPIRES |
2592000 (30 days) |
Two roles are supported:
| Role | Level | Capabilities |
|---|---|---|
admin |
2 | Full access: create/delete projects, generate reports, manage all data |
viewer |
1 | Read-only: view projects, reports, analytics, timeline |
The role is embedded in the JWT access token claims and enforced per endpoint by RequireRole middleware.
Set MAKE_VIEWER_ENDPOINTS_PUBLIC=true to skip authentication for viewer-role endpoints. This is useful for public dashboards where you want reports accessible without login.
AllureDeck uses the double-submit cookie pattern for CSRF protection.
- Active only when
SECURITY_ENABLED=true - On login, a
csrf_tokencookie is set - Mutating requests (POST, PUT, DELETE, PATCH) must include
X-CSRF-Tokenheader matching the cookie value - Comparison uses
crypto/subtle.ConstantTimeCompareto prevent timing attacks - Exempt:
GET,HEAD,OPTIONSmethods and the/loginendpoint
Per-IP token bucket rate limiting protects the API from abuse:
- Each IP gets an independent token bucket
- Returns
429 Too Many RequestswithRetry-After: 1header when the bucket is empty - Stale IP entries are cleaned up in the background
If AllureDeck runs behind nginx, a load balancer, or another reverse proxy, set TRUST_FORWARDED_FOR=true so the rate limiter uses the real client IP from the X-Forwarded-For header rather than the proxy's IP.
The following headers are added to every API response:
| Header | Value |
|---|---|
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
Content-Security-Policy |
default-src 'self' |
Enable TLS on the API server with TLS=true. Requires two additional env vars:
TLS_CERT_FILE— path to the TLS certificate fileTLS_KEY_FILE— path to the TLS private key file
In Kubernetes deployments, TLS is typically terminated at the ingress layer rather than on the application server. See helm-chart.md for ingress TLS configuration.
Before deploying to production:
- Set
SECURITY_ENABLED=true - Set
JWT_SECRET_KEYto a strong random value (min 32 chars):openssl rand -hex 32 - Change the default
admin/admincredentials - Set a strong viewer password (or disable the viewer account)
- Set
CORS_ALLOWED_ORIGINSto your UI domain (e.g.https://alluredeck.example.com) - Set
TRUST_FORWARDED_FOR=trueif running behind a reverse proxy - Use HTTPS — either via
TLS=trueon the API or at the ingress/load balancer layer - In Kubernetes: use
api.existingSecretto supply credentials from a secrets manager, not plain Helm values
- configuration.md — full environment variable reference
- helm-chart.md — Kubernetes secrets management