# Multi-factor authentication in PnP iOS SDK

> Web3Auth PnP iOS SDK - Multi Factor Authentication | Embedded Wallets

At Web3Auth, we prioritize your security by offering Multi-Factor Authentication (MFA). MFA is an extra layer of protection that verifies your identity when accessing your account. To ensure ownership, you must provide two or more different backup factors. You have the option to choose from the device, social, backup factor (seed phrase), and password factors to guarantee access to your Web3 account. Once you create a recovery factor, MFA is enabled, and your keys are divided into three shares for offchain multi-sig, making the key self-custodial. With backup factors, you can easily recover your account if you lose access to your original device or helps login into a new device.

:::note

This is a paid feature and the minimum [pricing plan](https://web3auth.io/pricing.html) to use this SDK in a production environment is the **Scale Plan**. You can use this feature in Web3Auth Sapphire Devnet network for free.

:::

## Enable using the Multi-Factor Authentication level

For a dapp, we provide various options to set up Multi-Factor Authentication. You can customize the MFA screen by passing the `mfaLevel` parameter in `login` method. You can enable or disable a backup factor and change their order. Currently, there are four values for MFA level.

:::caution Note

If you are using default verifiers, your users may have set up MFA on other dapps that also use default Web3Auth verifiers. In this case, the MFA screen will continue to appear if the user has enabled MFA on other dapps. This is because MFA cannot be turned off once it is enabled.

:::

### MFA level options

| MFA Level | Description                                                |
| --------- | ---------------------------------------------------------- |
| DEFAULT   | Shows the MFA screen every third login.                    |
| OPTIONAL  | Shows the MFA screen on every login, but user can skip it. |
| MANDATORY | Makes it mandatory to set up MFA after first login.        |
| NONE      | Skips the MFA setup screen.                                |

### Usage

```swift

let web3auth = Web3Auth(W3AInitParams(
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  network: .sapphire_mainnet,
  redirectUrl: "bundleId://auth"
))

let result = try await web3Auth.login(
  W3ALoginParams(
    loginProvider: .GOOGLE,
    // focus-next-line
    mfaLevel: .MANDATORY
  )
)
```

## Explicitly enable MFA

The `enableMFA` method is used to trigger MFA setup flow for users. The method takes `W3ALoginParams` which will used during custom verifiers. If you are using default login providers, you don't need to pass `W3ALoginParams`. If you are using custom JWT verifiers, you need to pass the valid JWT token in `W3ALoginParams` as well.

<Tabs
  defaultValue="default-verifier"
  values={[
    { label: "Default Verifier", value: "default-verifier" },
    { label: "Custom JWT Verifier", value: "custom-jwt-verifier" },
  ]}
>

<TabItem value = "default-verifier">

```swift
do {
	// focus-next-line
  let isMFAEnabled = try await web3Auth.enableMFA()
} catch {
  print(error.localizedDescription)
  // Handle Error
}
```

</TabItem>

<TabItem value = "custom-jwt-verifier">

```swift
do {
  let loginParams = W3ALoginParams(
    loginProvider: .JWT,
    extraLoginOptions: .init(id_token: "your_jwt_token")
   )

  let isMFAEnabled = try await web3Auth.enableMFA(loginParams)

} catch {
  print(error.localizedDescription)
  // Handle Error
}

```

</TabItem>
</Tabs>

## Configure Multi-Factor Authentication settings

You can configure the order of MFA or enable/disable MFA type by passing the `mfaSettings` object in `Web3AuthOptions`.

:::note Note

- At least two factors are mandatory when setting up the mfaSettings.
- If you set `mandatory: true` for all factors, the user must set up all four factors.
- If you set `mandatory: false` for all factors, the user can skip setting up MFA. But at least two factors are mandatory.
- If you set `mandatory: true` for some factors and `mandatory: false` for others, the user must set up the mandatory factors and can skip the optional factors. But, the user must set up at least two factors.
- The `priority` field is used to set the order of the factors. The factor with the lowest priority will be the first factor to be set up. The factor with the highest priority will be the last factor to be set up.

:::

### Parameters - `MfaSettings`

`MfaSettings` allows you to set the type of the MFA.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter              | Description                                                              |
| ---------------------- | ------------------------------------------------------------------------ |
| `deviceShareFactor?`   | MFA setting for deviceShareFactor. It accepts `MfaSetting` as a value.   |
| `backUpShareFactor?`   | MFA setting for backUpShareFactor. It accepts `MfaSetting` as a value.   |
| `socialBackupFactor?`  | MFA setting for socialBackupFactor. It accepts `MfaSetting` as a value.  |
| `passwordFactor?`      | MFA setting for passwordFactor. It accepts `MfaSetting` as a value.      |
| `passkeysFactor?`      | MFA setting for passkeysFactor. It accepts `MfaSetting` as a value.      |
| `authenticatorFactor?` | MFA setting for authenticatorFactor. It accepts `MfaSetting` as a value. |

</TabItem>

<TabItem value="class">

```swift
	public struct MfaSettings: Codable {
        public init(deviceShareFactor: MfaSetting?, backUpShareFactor: MfaSetting?, socialBackupFactor: MfaSetting?, passwordFactor: MfaSetting?, passkeysFactor: MfaSetting?, authenticatorFactor: MfaSetting?) {
            self.deviceShareFactor = deviceShareFactor
            self.backUpShareFactor = backUpShareFactor
            self.socialBackupFactor = socialBackupFactor
            self.passwordFactor = passwordFactor
            self.passkeysFactor = passkeysFactor
            self.authenticatorFactor = authenticatorFactor
        }

        let deviceShareFactor: MfaSetting?
        let backUpShareFactor: MfaSetting?
        let socialBackupFactor: MfaSetting?
        let passwordFactor: MfaSetting?
        let passkeysFactor: MfaSetting?
        let authenticatorFactor: MfaSetting?
    }
```

</TabItem>
</Tabs>

### Parameters - `MfaSetting`

`MfaSetting` allows you to configure the behavior of an individual MFA factor.

<Tabs
  defaultValue="table"
  values={[
    { label: "Table", value: "table" },
    { label: "Class", value: "class" },
  ]}
>

<TabItem value="table">

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `enable`     | Enable/Disable MFA. It accepts `Bool` as a value.                               |
| `priority?`  | Priority of MFA. It accepts `Int` as a value, where valid range is from 1 to 4. |
| `mandatory?` | Mandatory/Optional MFA. It acccepts `Bool` as a value.                          |

</TabItem>

<TabItem value="class">

```swift

    public struct MfaSetting: Codable {
        public init(enable: Bool, priority: Int?, mandatory: Bool? = nil) {
            self.enable = enable
            self.priority = priority
            self.mandatory = mandatory
        }

        let enable: Bool
        let priority: Int?
        let mandatory: Bool?
    }

```

</TabItem>
</Tabs>

### Usage

```swift

let web3auth = try await Web3Auth(W3AInitParams(
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  network: .sapphire_mainnet,
  redirectUrl: "bundleId://auth",
  // focus-start
  whiteLabel: W3AWhiteLabelData(
    mfaSettings: MfaSettings(
      deviceShareFactor: MfaSetting(enable: true, priority: 1),
      backUpShareFactor: MfaSetting(enable: true, priority: 2),
      socialBackupFactor: MfaSetting(enable: true, priority: 3),
      passwordFactor: MfaSetting(enable: true, priority: 4),
      passkeysFactor: MfaSetting(enable: true, priority: 5),
      authenticatorFactor: MfaSetting(enable: true, priority: 6)
    )
  )
  // focus-end
))

let result = try await web3Auth.login(
  W3ALoginParams(
    loginProvider: .GOOGLE,
    // focus-next-line
    mfaLevel: .MANDATORY
  )
)
```
