# Account security

> Protect your dashboard sign-in with two-factor authentication: authenticator apps, passkeys or security keys, recovery codes and an organization policy.

Signing in to the dashboard starts with an email code or your Google or GitHub account (see
[Create an account](https://developers.openwaf.dev/fundamentals/create-account/)). **Two-factor authentication** (2FA) adds a second step: after that
first sign-in, the dashboard also asks for a code from an authenticator app or for one of your passkeys or security
keys. Someone who gets into your mailbox or your Google or GitHub account still cannot open your organizations.

You manage it in **Account › Security** (`/profile/security` on the dashboard). Organization owners and admins can also
[require 2FA](#require-2fa) from every member.

## Second factors

| Factor | What it is | Notes |
|---|---|---|
| **Authenticator app** (TOTP) | A 6-digit code that changes every 30 seconds, from an app such as 1Password, Google Authenticator, Microsoft Authenticator or Aegis | One app per account. Each code works once. |
| **Passkey or security key** (WebAuthn) | A passkey stored on your phone, computer or password manager, or a hardware security key | You can register several and give each a name. A passkey can also [sign you in on its own](#passkey-sign-in). |
| **Recovery codes** | 10 single-use codes in the form `xxxxx-xxxxx` | Created with your first factor and shown only once. Keep them offline, for example in a password manager or on paper. |

2FA is **on** as soon as you have a confirmed authenticator app or at least one passkey or security key. We recommend
registering two factors (for example an app and a security key, or passkeys on two devices) so that losing one device
does not lock you out.

> **Note**
>
> Passkeys and security keys belong to the dashboard address where you register them. One registered on
> `dash.openwaf.dev` does not work on a [white-label dashboard](https://developers.openwaf.dev/fundamentals/white-label/) such as
> `dash.youragency.com`, and vice versa: register one on each address you use. Authenticator apps and recovery codes work
> everywhere.


## Turn on two-factor authentication

1. Open **Account › Security**.
2. Add a first factor:
   - **Authenticator app**: scan the QR code with the app (or type the secret it shows), then enter the 6-digit code
     the app displays to confirm it.
   - **Passkey or security key**: give it a name (1–64 characters, for example «Work laptop») and follow your browser's
     prompt.
3. Save the **10 recovery codes** the dashboard shows. They are not shown again.


Turning on 2FA signs you out of every **other** session, on every device; the session you are using stays open. Adding
more factors later, while 2FA is already on, asks you to [confirm it's you](#step-up) first.

## Signing in with 2FA

After the email code, the email link or Google/GitHub, the dashboard shows a second step and offers the factors you
have: a code from your app, a passkey or security key, or a recovery code. Until you complete it, the session can do
nothing else: your organizations are not even listed.

- **Remember this device**: tick it on the second step to skip it on this browser for **30 days**. The next sign-in
  still starts with your email code or Google/GitHub. Removing a factor, turning off 2FA, a
  [support-assisted reset](#lost-device) and **Sign out everywhere** forget every remembered device; you can also
  forget them yourself in **Account › Security**. Accounts of OpenWAF platform operators never skip the second step.
- **Lockout**: 5 failed attempts in a row, with any factor, block the second step for 15 minutes. A failed attempt is
  a wrong or already-used app code, a wrong or already-used recovery code, or a passkey or security key whose signature
  does not verify. Cancelling the browser's passkey prompt does not count. A wrong code tells you how many attempts are
  left.
- Using a recovery code tells you how many are left. Generate a new set before you run out.

## Sign in with a passkey

On the sign-in page, **Sign in with a passkey** signs you in with a passkey alone, without an email code. The browser
offers the passkeys you registered on that dashboard address and asks you to unlock them (fingerprint, face, PIN or the
device password). Because a passkey proves both that you hold the device and that you unlocked it, this sign-in already
counts as two-factor.

The button only appears in browsers that support passkeys. A security key that is not a discoverable passkey can still
be used as the second step after an email code.

## Confirm it's you

Some actions need a recent confirmation, even in a session that is already signed in: if you have not confirmed your
identity in the last **10 minutes**, the dashboard asks you to **confirm it's you** and then carries on with the action.
You confirm with one of your factors, or, if you do not use 2FA, with a code sent to your email address.

| Action | Where |
|---|---|
| Create an API token | **API tokens** |
| Change a member's role | **Members** |
| Add or invite a member as **Owner** or **Admin** | **Members** |
| Delete a domain | The domain's settings |
| Change the organization's settings | Organization settings |
| Turn on or off [Require 2FA](#require-2fa) | Organization settings |
| Delete your account | **Account** |
| Turn off 2FA, remove a factor, generate new recovery codes, or add a factor when 2FA is already on | **Account › Security** |

Signing in with a [remembered device](#sign-in) does not count as a confirmation, so these actions still ask for a
factor. The confirmation only applies to dashboard sessions: [API tokens](https://developers.openwaf.dev/fundamentals/api-tokens/) and MCP
connections never ask for it.

## Require 2FA for an organization

Owners and admins can require two-factor authentication from every member in the organization's settings. To turn it on
you need 2FA on your own account, and the change asks you to [confirm it's you](#step-up).

While the policy is on:

- A member without 2FA who opens the organization is sent to **Account › Security** to set it up before they can do
  anything in it. Their other organizations keep working.
- A member who signs in while the policy applies to them must add a factor before anything else; once it is
  confirmed, the session continues without signing in again.
- Members cannot turn off 2FA, or remove their last factor, while an organization they belong to requires it.
- **Members** shows who has 2FA on, so you can follow up with whoever has not set it up yet.

Turning the policy on or off is recorded in the audit log as `org.2fa_policy`. The policy binds sessions that are
already open: their next request in the organization is sent to set up 2FA, without signing in again. Accounts of
OpenWAF platform operators always need 2FA, whatever their organizations decide; an operator session opened before
the account had 2FA is likewise sent to set it up on its next request.

## MCP connections need 2FA

Granting an AI assistant access through [OAuth](https://developers.openwaf.dev/mcp/oauth-and-tokens/#connecting-with-oauth) requires a session that
passed two-factor authentication. If your account has no 2FA yet, the consent screen asks you to turn it on first. MCP
clients that use an API token are not affected.

## API tokens are not affected

2FA protects dashboard sign-in. [API tokens](https://developers.openwaf.dev/fundamentals/api-tokens/) (`owf_…`) and existing MCP OAuth connections
keep working as they are, and the require-2FA policy does not block them: they carry their own role, scope and expiry.
Creating a new token from the dashboard asks you to [confirm it's you](#step-up). Revoke tokens you no longer need in
**API tokens**.

## Manage your factors and sessions

In **Account › Security** you can:

- Rename or remove passkeys and security keys, and remove the authenticator app (to move to a new phone, remove it and
  add it again).
- Generate a new set of recovery codes; the previous codes stop working at once.
- Turn off 2FA, which removes every factor, the recovery codes and the remembered devices. Not possible while 2FA is
  required for you.
- Forget every remembered device.
- See your open sessions (sign-in method, IP address, browser, when they started and when they were last used) and end
  any of them.

Every change is recorded in the audit log of each organization you belong to:

| Action | Meaning |
|---|---|
| `user.2fa.enable`, `user.2fa.disable` | 2FA turned on or off |
| `user.2fa.factor_add`, `user.2fa.factor_remove` | An authenticator app, passkey or security key added or removed |
| `user.2fa.verify_fail`, `user.2fa.lockout` | A wrong second-factor code, and the 15-minute lockout |
| `user.2fa.recovery_used`, `user.2fa.recovery_regenerate` | A recovery code used, or a new set generated |
| `user.2fa.reset` | Factors removed by OpenWAF support (see below) |

## If you lose your device

1. **Use a recovery code.** On the second step, choose the recovery code option and enter one of your codes. Then, in
   **Account › Security**, remove the lost factor, add a new one and generate new recovery codes.
2. **Use another factor.** Any other passkey, security key or the authenticator app you registered works as well.
3. **Contact support.** If you have no factor and no recovery code left, write to
   [support@openwaf.dev](mailto:support@openwaf.dev) from the email address of your account.


Support resets two-factor authentication only after verifying your identity. We may ask for details that only the
account holder knows and, when you belong to an organization with other owners or admins, ask one of them to confirm the
request. A reset removes every factor, recovery code and remembered device, ends all your sessions on every device and
is recorded as `user.2fa.reset`, with the reason, in the audit log of every organization you belong to. You then sign in
again and set up 2FA from scratch; if an organization requires it, you must do so before working in it.

> **Caution**
>
> Support never asks for your sign-in codes, recovery codes or authenticator secrets. Do not share them with anyone.
