## Multi-Factor Authentication (MFA)  
MFA adds an extra layer of security to user accounts by requiring a second authentication factor beyond a password. Medplum supports two MFA methods:
- **Authenticator app (TOTP)** — a Time-based One-Time Password compatible with authenticator apps like Google Authenticator, Microsoft Authenticator, Authy, and others.
- **Email** — a single-use 6-digit code emailed to the user's address each time it is needed.

By default, only the authenticator app (TOTP) method is offered. Email-based MFA must be enabled per [`Project`](/content/docs/api/fhir/medplum/project/index.html) via the [`allowedMfaMethods`](/content/docs/auth/mfa#configuring-allowed-mfa-methods/index.html) setting. Users may enroll in more than one method and choose which to use at login.

### Configuring allowed MFA methods  
The MFA methods that users in a Project can enroll in are controlled by the `allowedMfaMethods` setting on the [`Project`](/content/docs/api/fhir/medplum/project/index.html) resource. It is stored as a single [`Project.setting`](/content/docs/self-hosting/project-settings/index.html) entry whose `valueString` is a comma-delimited list of method codes:

| Value | Methods offered |
| --- | --- |
| _(unset)_ | Authenticator app (TOTP) only — the historical default |
| `totp` | Authenticator app (TOTP) only |
| `email` | Email codes only |
| `totp,email` | Both — users choose which to enroll in and which to use at login |

When the setting is missing, empty, or contains no recognized value, Medplum falls back to `totp` only.

### Enabling email-based MFA  
To allow users in a Project to use email-based MFA, set the `allowedMfaMethods` setting to include `email`. `Project` settings can be edited by a Project Admin, or in the Medplum App by a Super Admin on the Project edit page.

```ts
const project = await medplum.readResource('Project', projectId);
await medplum.updateResource({
  ...project,
  setting: [
    ...(project.setting ?? []).filter((s) => s.name !== 'allowedMfaMethods'),
    { name: 'allowedMfaMethods', valueString: 'totp,email' },
  ],
});
```

### Branding MFA emails and authenticator apps  
By default, MFA content names Medplum. A Project can white-label it with an `appName` [`Project.setting`](/content/docs/self-hosting/project-settings/index.html) entry.

### Self-Enrollment  
Users can self-enroll in MFA through the Medplum App security settings. The methods offered depend on the Project's [`allowedMfaMethods`](/content/docs/auth/mfa#configuring-allowed-mfa-methods/index.html) setting.

#### Steps to Self-Enroll  
1. Navigate to the Security page at `https://app.medplum.com/security`
2. You will see the "Multi Factor Auth" section showing your current enrollment status
3. Choose a method to enroll in:
   - **Authenticator app (TOTP)**  
      
   - **Email**  
      - Click **"Add email-based MFA"** — a 6-digit code is emailed to your account's address
      - Enter the code to verify control of your email and complete enrollment

Once enrolled, you will be required to provide an MFA code during login. When both methods are allowed, a user can enroll in both.

### Requiring MFA  
To require MFA for every user who signs in to a Project with a username and password, add an `mfaRequired` entry to [`Project.setting`](/content/docs/self-hosting/project-settings/index.html) with `valueBoolean: true`.

### Admin MFA Reset  
Project admins can reset MFA for members who have lost access to a factor via the `POST /admin/projects/:projectId/members/:membershipId/mfa/reset` endpoint. The request body accepts an optional `method` field:
| `method` | Effect |
| --- | --- |
| _(omitted)_ | Resets `totp` — the backwards-compatible default |
| `totp` | Resets the authenticator app factor and rotates the TOTP secret |
| `email` | Resets the email factor; the TOTP secret is left untouched |

### Admin Password Reset  
Project admins can send a member a password reset email via the `POST /admin/projects/:projectId/members/:membershipId/resetpassword` endpoint.

### How email-based MFA works  
Unlike the authenticator app method, which derives codes from a shared secret, email-based MFA issues a fresh single-use code each time one is needed.

### Using Medplum's SignInForm Component  
**We recommend using Medplum's [`SignInForm`](https://storybook.medplum.com/?path=/story/medplum-auth-signinform--basic) React component** for handling authentication flows that include MFA.
