> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-factor authentication

> Require approvals from different validator configurations.

Choose multi-factor authentication (MFA) when a transaction should require different validator configurations, such as an ECDSA key and a passkey. MFA wraps those configurations as subvalidators and enforces an overall threshold.

This differs from [multisig](/wallets/custom-signer/account-setup/native-signers/multisig), which sets a threshold within one ECDSA or passkey validator.

## Configure MFA

Use the registry-free MFA module for a new account. The default legacy MFA module checks the ERC-7484 registry during installation and cannot be installed on a fresh account.

```ts theme={null}
import {
  MULTI_FACTOR_VALIDATOR_V2_ADDRESS,
  RhinestoneSDK,
} from '@rhinestone/sdk'

const rhinestone = new RhinestoneSDK({
  auth: {
    mode: 'apiKey',
    apiKey: process.env.RHINESTONE_API_KEY!,
  },
})

const account = await rhinestone.createAccount({
  owners: {
    type: 'multi-factor',
    module: MULTI_FACTOR_VALIDATOR_V2_ADDRESS,
    threshold: 2,
    validators: [
      {
        type: 'ecdsa',
        accounts: [ecdsaOwner],
      },
      {
        type: 'passkey',
        accounts: [passkeyOwner],
      },
    ],
  },
})
```

This configuration requires both subvalidators. Each subvalidator can also define its own owner threshold.

The subvalidator ID is its zero-based position in `validators`: the ECDSA configuration above has ID `0`, and the passkey configuration has ID `1`. Use those IDs when you explicitly select MFA signers for a transaction. If you provide an explicit signer selection, repeat `module: MULTI_FACTOR_VALIDATOR_V2_ADDRESS` there so the signature targets the installed module.

## Manage MFA

Pass the V2 module address to every MFA management action. In SDK 2.16.1 these actions otherwise default to the legacy module, which is not the module installed above.

```ts theme={null}
import {
  changeThreshold,
  removeSubValidator,
  setSubValidator,
} from '@rhinestone/sdk/actions/mfa'

const replacePasskey = setSubValidator(
  1,
  { type: 'passkey', accounts: [replacementPasskeyOwner] },
  MULTI_FACTOR_VALIDATOR_V2_ADDRESS,
)
const removePasskey = removeSubValidator(
  1,
  { type: 'passkey', accounts: [passkeyOwner] },
  MULTI_FACTOR_VALIDATOR_V2_ADDRESS,
)
const requireOneFactor = changeThreshold(
  1,
  MULTI_FACTOR_VALIDATOR_V2_ADDRESS,
)
```

Submit these calls through the account's normal transaction flow. See the API reference for [`setSubValidator`](/wallets/custom-signer/sdk-reference/actions/mfa/set-sub-validator), [`removeSubValidator`](/wallets/custom-signer/sdk-reference/actions/mfa/remove-sub-validator), and [`changeThreshold`](/wallets/custom-signer/sdk-reference/actions/mfa/change-threshold).

Test recovery and factor replacement before using a threshold that can lock the account if one factor is lost.
