Authentication Configuration

Auth is stateless JWT (HS256) over bcrypt-hashed credentials, with optional TOTP MFA and, on Enterprise, federated SSO. This page covers the token lifecycle, user provisioning, and the hardening surface an operator owns.

Flow

POST /api/auth/login resolves the user by email, verifies the submitted password against the stored bcrypt hash, and on success issues a JWT carrying userId, email, name, role, signed HS256 with JWT_SECRET. The client holds it in localStorage and sends Authorization: Bearer <token> on every call; the backend re-verifies signature and expiry per request. Because the token is stateless, anyone with JWT_SECRET can forge one for any user, keep it in a secret store, out of source and client code.

Password Hashing

bcrypt at cost 12, ~200-300ms/hash, per-hash salt, format $2b$12$.... Don't drop below 10.

Provisioning Users

Registration API

POST /api/auth/register
{ "email": "user@company.com", "password": "…", "name": "Jane Smith" }

Password is hashed server-side; default role is developer, an admin adjusts it afterward.

Direct insert (bootstrap admin / bulk)

node -e "require('bcrypt').hash('YourPassword123', 12).then(h => console.log(h));"

INSERT INTO users (email, password_hash, name, role, is_active)
VALUES ('admin@company.com', '$2b$12$…', 'Admin User', 'admin', true);

Roles

RoleAccess
adminFull access, incl. user management and system settings.
developerAuthor/edit scripts, request approvals.
reviewerApprove/reject scripts.
deployerExecute scripts, manage releases.
viewerRead-only.

Token Lifecycle

TTL is JWT_EXPIRES_IN (default 8h). There is no refresh by design, on a 401 the client redirects to login. Logout clears client storage but, being stateless, the token stays cryptographically valid until expiry. To force a fleet-wide logout during an incident, rotate JWT_SECRET and restart, every outstanding signature fails at once.

Multi-Factor Authentication

Enterprise supports TOTP (RFC 6238) with 10 single-use backup codes stored as SHA-256 hashes; the TOTP secret is encrypted at rest with ENCRYPTION_KEY. Enrollment is POST /api/auth/mfa/setup then /enable.

Rate Limiting

Auth falls under the general bucket (GENERAL_RATE_LIMIT_MAX, default 2000 / 15 min per IP); DB DevOps routes use the wider DB_DEVOPS_RATE_LIMIT_MAX bucket. Breach returns 429. See Environment Variables for the knobs, and ensure the proxy forwards the real client IP or the per-IP keying is meaningless.

Hardening Checklist

Enterprise SSO

Enterprise adds SAML, OIDC, and LDAP federation plus connectors for Azure AD, Okta, Google Workspace, and AWS Cognito, managed at /api/auth/idp/providers. See the Identity Providers page.