TurboPanel Docs
Using TurboPanel

Account security

Your account is one identity across every organization you belong to, and the ways you prove it is you are managed in one place: the account menu → Security (/account/security). This chapter covers signing in, the second factor, passkeys, linked sign-in providers, password rules and recovery. Configuring which providers an instance offers is the operator's side, in Accounts and access.

The model

An account has an email address and up to four ways in:

Way inWhat it isSecond factor?
PasswordEmail + password, the way every account starts (except one created by GitHub or Google sign-in).Yes, when two-factor is on.
Two-factor codeA six-digit code from an authenticator app, or one of ten one-time backup codes, asked for after the password.— it is the second factor.
PasskeyA WebAuthn credential (Touch ID, Windows Hello, a security key, a phone) registered from a browser.No — a passkey sign-in never asks for a code; the passkey is the second factor.
Linked providerA GitHub or Google identity linked to this account.Yes, when two-factor is on: the code step follows the provider round trip.

Three rules run through everything below:

  1. Changing how you sign in needs a fresh proof. Enrolling or disabling two-factor, regenerating backup codes, adding or removing a passkey, and unlinking a provider all require re-authentication. An account that has a password must type it into the Current password field every time — a fresh session does not substitute. An account with no password (it signs in only with a passkey or a linked provider) is let through on a session younger than 15 minutes. Otherwise the request is refused (403) and the console asks for the password. Linking a provider is the one exception: it is a redirect and cannot carry a password, so it always uses the 15-minute window.
  2. Securing the account signs everyone else out. Each of those changes revokes every other session on the account and keeps only the one that made the change. A password reset revokes all sessions, including the one at the keyboard.
  3. You cannot remove your last way in. Unlinking the only provider on an account that has no password and no passkey is refused (last_sign_in_method). Keep at least two ways in before removing one.

Sessions last 7 days and are cookie-bound to the control plane's origin; the native apps use the same session against the control plane you connected to (Change control plane on the sign-in screen).

Sign in

Email and password → Sign In. On an instance with providers configured, Sign in with GitHub / Sign in with Google sit beside it, and Sign in with a passkey below.

If two-factor is on, the authentication code step follows: six digits from your app, or Use a backup code to type one of the ten. The challenge lives 5 minutes and dies after five wrong codes — go Back to sign in and start again rather than retrying a dead one.

A new account made by sign-up must verify its email first (the link in the mail is good for 24 hours); until then sign-in is refused with Verify your email before signing in. An instance without outbound email skips verification entirely.

There is no Forgot password link yet

The API carries an email-code password reset (POST /auth/reset-password/request-otp then POST /auth/reset-password/otp), but the console does not offer it in this release. If you lose your password, sign in with a passkey or a linked provider and keep going; otherwise ask the instance's administrator.

Turn on two-factor

Security → Two-factor authentication → Enable two-factor.

Enter your current password (re-authentication).

Add this to your authenticator: scan the QR code, or Copy key / Copy link (the base32 secret or the otpauth:// URI) into any TOTP app.

Type the first six-digit Authentication code and Verify and enable. Nothing is enabled until a code verifies.

Save your backup codes. Ten one-time codes, shown once. Copy all, store them where you can reach them without this device, then I've saved these. They are the only way back in if you lose the authenticator.

Afterwards the panel shows the method and how many backup codes remain. Regenerate backup codes issues ten new ones and invalidates the old set; Disable two-factor removes the authenticator and the codes. Both re-authenticate.

Add a passkey

Security → Passkeys → Add a passkey. Web only in this release — the native apps show a use a browser note instead of a button, because a passkey must be created on the control plane's own origin.

Enter your current password if asked, and give the passkey a name (the device or authenticator it lives on).

Complete the browser's prompt. User verification is required — a fingerprint, face, device PIN or security-key PIN, not just a touch.

The list shows each passkey's name, when it was added, and where it lives — Synced (a multi-device credential backed up by its provider), Multi-device, or This device only. Remove re-authenticates; a passkey registered twice is refused (passkey_exists).

To sign in with it: Sign in with a passkey on the sign-in screen — no email, no password, no code.

Security → Linked accounts. Only providers the instance has configured appear. Linking is web-only (Link from a browser on native).

Link next to the provider. Your session must be younger than 15 minutes (otherwise Sign in again to link an account).

Authorize at the provider. You return to Security with Account linked.

TurboPanel stores the provider identity only — no provider tokens. A provider identity already linked to a different user is refused (That provider account is already linked to another user). Unlink re-authenticates and is refused when it would leave no way in.

No linking by email address

Signing in with a provider whose identity is linked to no account never joins an existing account just because the email matches. It creates a new account when sign-up is open, or fails with New accounts cannot be created this way when it is closed. Link from the signed-in Security screen instead.

Passwords

The same rule is enforced on every path that sets a password (install, sign-up, reset): at least 8 characters, at most 256, at least one number, at least one of $ ! @ % & * # ^ ( ) _ + = -, and no leading or trailing space. The sign-up form additionally checks the password against the Have I Been Pwned range API in the browser (k-anonymity — five hash characters leave the device) and refuses a known-breached one; see Password safety. There is no change-password screen in this release.

Reference

ItemValue
Session lifetime7 days (cookie, HttpOnly, SameSite=Lax)
Re-authenticationpassword accounts: the current password, always; password-less accounts and provider linking: a session younger than 15 minutes
Two-factor challenge5 minutes; five wrong codes end it
AuthenticatorRFC 6238 TOTP, six digits
Backup codes10, one-time, shown once; regenerate replaces all
PasskeysWebAuthn, user verification required, discoverable, ES256 / RS256; web only
Email verification24-hour link; skipped when the instance sends no mail
Password8–256 characters, a number, a special character, no edge whitespace
Sessions revoked on2FA on/off, backup codes regenerated, passkey added/removed, provider linked/unlinked (all but the current); password reset (all)

Errors

Account routes answer with a short error string; the console shows the sentence in the table.

ErrorStatusMeaning
Invalid credentials401Wrong email or password — the same answer whether or not the account exists.
Verify your email before signing in…403The sign-up link has not been opened yet.
Reauthentication required403Type your current password (a password-less account: sign in again — the 15-minute window has passed).
two_factor_enabled409Two-factor is already on; disable it before enrolling again.
Not enrolled, Invalid code400Verify was called without a pending enrollment, or the code did not match.
Invalid or expired challenge400The 5-minute sign-in challenge is over; sign in again.
Too many attempts429Five wrong codes; sign in again.
passkey_exists409That authenticator is already registered on the account.
Invalid credential400The browser's WebAuthn response did not verify (wrong origin, counter went backwards, no user verification).
Not found404The passkey is not on this account.
last_sign_in_method409Unlinking would leave no password, passkey or other provider.
oauth_state_invalidredirectSign-in expired. Try again. — the 10-minute provider round trip took too long or was tampered with.
oauth_exchange_failedredirectCould not complete sign-in. — the provider refused the code exchange.
oauth_signup_disabledredirectNew accounts cannot be created this way. — no linked account and sign-up is closed.
account_conflictredirectThe provider identity belongs to another user.
account_disabledredirectThe account is disabled.
oauth_reauth_required, oauth_unauthenticatedredirectLinking needs a recent sign-in, or the session ended during the round trip.
Not configured503The instance has no root secret or that provider is not set up.
Edit on GitHub

Last updated on

On this page