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.

Self-Service Password Reset

The sign-in screen shows a Forgot password? link for local (password) accounts. It routes to /forgot-password, where the user enters their email; the server mints a single-use, one-hour reset token and emails a link to /reset-password?token=… where they choose a new password. To prevent account enumeration the request endpoint always returns success, whether or not the email matches an account.

Email delivery is required for this to work. Configure SMTP (SMTP_HOST + SMTP_FROM, plus SMTP_PORT/SMTP_SECURE/SMTP_USER/SMTP_PASS as needed) so the app can send the reset email; MAIL_FROM overrides the envelope sender if set. Set APP_PUBLIC_URL to your externally reachable base URL so the link in the email is absolute (e.g. https://dbstudio.yourcompany.com). If no mail transport is configured the token is still minted but no email is sent, and the reset cannot complete, so treat SMTP as mandatory wherever local logins are used. SSO-managed users should reset at their identity provider instead.

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.