Authentication

How users log in to Temps, manage their credentials, and recover access.


Login methods

Temps supports several login methods. You can enable or disable them per instance in Settings → Authentication.

Email + Password

Traditional credentials with secure password hashing. Passwords must be at least 8 characters (max 128) and include an uppercase letter, a lowercase letter, a digit, and a special character.

Magic Links

Passwordless login — the user enters their email address and receives a one-time link valid for a short window. More resistant to phishing than passwords because there is no reusable credential to steal.

Single Sign-On (OIDC)

Log in with any standards-compliant OpenID Connect identity provider — Keycloak, Auth0, Okta, Authentik, Zitadel, Microsoft Entra (Azure AD), Google Workspace, and others. Features:

  • PKCE authorization code flow with nonce/state validation
  • Just-in-time user provisioning on first login
  • Group-to-role mapping (IdP groups → Temps roles)
  • Per-provider trust_idp_email flag for corporate IdPs that don't emit email_verified

See OIDC SSO for setup instructions and the full hardening reference.


Two-Factor Authentication

Users can enable TOTP-based 2FA (Google Authenticator, Authy, 1Password, and any RFC 6238-compatible app) from their account settings. Once enabled:

  • Every login with email + password or magic link requires a TOTP code
  • Changing the account password requires passing the MFA challenge before the change is committed
  • API keys bypass MFA (they are pre-authorized tokens scoped to specific permissions)

Admins can require 2FA for all members of a project via Settings → Security.


API Keys

API keys are long-lived tokens for programmatic and CI/CD access. They are scoped to specific permissions and can be revoked at any time.

Creating a key

Go to Settings → API Keys → Create Key. Choose a name, expiry (or no expiry), and one or more permission scopes.

Available scopes

ScopeWhat it allows
read:projectsView projects and their settings
write:projectsCreate and modify projects
read:deploymentsView deployments and build logs
write:deploymentsTrigger and manage deployments
read:analyticsView analytics data
admin:projectFull access to a single project

Best practices

  • Create one key per integration — never share keys across systems
  • Set an expiry for keys used in ephemeral environments (CI/CD)
  • Rotate keys regularly and revoke any that are no longer in use
  • Use the narrowest scope that the integration actually needs

Account security

PropertyBehavior
Password storageBcrypt hash — the plaintext is never stored
Session managementSessions are stored server-side; logout invalidates the session immediately
Token expirationSession tokens have a configurable maximum lifetime
Brute-force protectionRepeated failed logins trigger a lockout with exponential back-off
Login enumerationError messages are constant ("Invalid email or password") regardless of whether the address exists

Self-service password reset

Users who are locked out can request a password reset from the login screen. The reset link is delivered only by email to the requesting user — it is never forwarded to Slack, webhooks, or admin inboxes.

Requirements: An email provider must be configured and enabled. A Slack-only notification setup does not count. The "Forgot password?" link on the login form appears only when the server reports password_reset_available: true via GET /api/auth/email-status.

How it works:

  1. The user enters their email on /forgot-password. The response is always the same ("if an account exists, a link has been sent") regardless of whether the address exists — preventing user enumeration.
  2. The reset email links to {base_url}/auth/reset-password?token=…. The token expires in 1 hour.
  3. The user sets a new password. Complexity rules match the backend: ≥8 characters (max 128), uppercase, lowercase, digit, and special character.

Endpoints:

EndpointMethodPurpose
/api/auth/password-reset/requestPOSTRequest a reset link (always 200; 503 if no email provider)
/api/auth/password-reset/verifyPOSTSet a new password using { token, new_password }
/api/auth/email-statusGETReturns email_configured, magic_link_available, password_reset_available

In-app password change

Logged-in users can change their password from the account settings page — no email link or logout required. This is distinct from the password reset flow above, which is for users who are already locked out.

Where to find it: Account settings (profile page), available to authenticated users only.

How it works:

  1. The user enters their current password to re-authenticate before any change is accepted.
  2. If MFA is enabled, the user must pass the TOTP challenge after the current-password check. The change is not committed until MFA succeeds.
  3. The user enters and confirms a new password (same complexity rules apply).
  4. On success, all other active sessions are revoked — only the session that performed the change remains alive. This ensures that if the old credentials were compromised, any concurrent attacker sessions are immediately terminated.

Comparison:

In-app password changeSelf-service password reset
Who can use itLogged-in usersLogged-out users (forgot password)
AuthenticationCurrent password + optional MFAEmail reset link (expires in 1 hour)
Session effectAll other sessions revokedNo effect on existing sessions
Email provider requiredNoYes

Was this page helpful?