# MFA

> Require a verified second factor on the tables you choose, and enroll and step up factors from the client.

Source: https://bettersupabase.com/docs/blocks/mfa

`mfa` installs `better_supabase.mfa_satisfied()`, which a restrictive policy
calls to require a second factor. It returns true when the caller has no
verified factor, or verified one in this session (`aal2` in the token). A user
who enrolled a factor must use it before the policy lets them through.

```bash
better-supabase add mfa
```

Add the policy to each table that needs the second factor. It is
restrictive, so it applies on top of the table's other policies:

```sql title="supabase/schemas/invoices.sql"
create policy mfa_required on public.invoices as restrictive
  for all to authenticated
  using ((select better_supabase.mfa_satisfied()))
  with check ((select better_supabase.mfa_satisfied()));
```

## Client [#client]

`better-supabase/blocks/mfa` has two headless controllers over the Supabase
Auth MFA API. `createMfaController` lists, enrolls, verifies and removes
factors. `createStepUpController` asks for a code when a request failed
because the session is still at `aal1`, and `needsStepUp(error)` tells you
when that happened.

```ts
import {
  createMfaController,
  createStepUpController,
  needsStepUp,
} from "better-supabase/blocks/mfa";
```

The [MFA setup recipe](/docs/registry/ui-recipes/mfa-setup) renders
enrollment with your shadcn components. [MFA and SSO](/docs/auth/mfa-sso)
covers the Auth settings and step-up flows.