> For the complete documentation index, see [llms.txt](/llms.txt).

# Email passwordless with Embedded Wallets

Email passwordless sends a one-time passcode (OTP) or magic link to the user's email address. Choose the default connection for the quickest setup, or create a custom connection when you want the email field and OTP to stay inside the [modal](/embedded-wallets/sdk/react/advanced/whitelabel/)instead of a popup.

![Email passwordless onboarding](/assets/images/email-passwordless-onboarding-8baec498841e3b201d694c345b6103c8.png) 

## Default email passwordless[​](#default-email-passwordless "Direct link to Default email passwordless")

The default connection uses the email OTP service managed by Embedded Wallets. Enable **Email Passwordless** and the SDK reads it from the dashboard. You don't add an Auth Connection ID.

### Caveats[​](#caveats "Direct link to Caveats")

- With the modal, the user enters their email address and OTP in a **popup**, not in the modal itself.
- The default connection and a custom email connection are separate connections, so they produce different wallet addresses for the same person unless you link them with a [group connection](/embedded-wallets/authentication/group-connections/).

### Configure the default connection[​](#configure-the-default-connection "Direct link to Configure the default connection")

1. Open your project in the [MetaMask Developer Dashboard](https://developer.metamask.io).
2. Select **Social Connections**.
3. Enable **Email Passwordless**.
![Email Passwordless in the Social Connections settings](/assets/images/email-passwordless-toggle-a81bd77c78231ef979cf2e3c4073f914.png) 

## Custom email passwordless[​](#custom-email-passwordless "Direct link to Custom email passwordless")

A custom email connection on the dashboard is only an identifier. You don't paste SMTP credentials, an OAuth client ID, or a JWT JWKS URL. You create the connection, copy the **Auth Connection ID**, and pass that ID in your SDK configuration.

Login stays in the modal

Default email login opens a popup so the user can enter their address and OTP. When you attach your Auth Connection ID to `email_passwordless` in `modalConfig.loginMethods`, that input stays inside the modal.

Preserve wallet addresses

Decide between the default and a custom connection before you onboard users. Moving from the default email connection to a custom email connection changes every user's wallet address unless both connections are in a [group connection](/embedded-wallets/authentication/group-connections/) with matching user identifiers.

### Create the connection[​](#create-the-connection "Direct link to Create the connection")

1. Open **Social Connections** in the [MetaMask Developer Dashboard](https://developer.metamask.io).
2. Select the settings icon next to **Email Passwordless**.
3. Enter an **Auth Connection ID**.
4. Select **Add Connection**.
![Add a custom email passwordless connection](/assets/images/email-passwordless-add-connection-d5297005aa38ad50040680ba28f6c527.png) 

There are no other fields. If you already issue email OTPs from your own backend, use a [custom JWT connection](/embedded-wallets/authentication/custom-connections/custom-jwt/) instead of this dashboard identifier.

## Group email connections[​](#group-email-connections "Direct link to Group email connections")

A [group connection](/embedded-wallets/authentication/group-connections/) gives the same person one wallet address across several login methods, for example email passwordless and Google.

Default email and a custom email connection are separate. They produce different wallet addresses unless you group them and every connection in the group uses the same JWT user identifier (`email`).

Pass both the child connection ID and grouped connection ID when you bypass the modal:

```
await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  authConnectionId: '<EMAIL_AUTH_CONNECTION_ID>',
  groupedAuthConnectionId: '<GROUPED_AUTH_CONNECTION_ID>',
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

## Usage examples[​](#usage-examples "Direct link to Usage examples")

Use `login_hint` for the email address when you call `connectTo`. For the modal, pass the Auth Connection ID in `loginMethods` so the flow stays in the modal.

### Default implicit flow

Pass the user's email address as `login_hint`. The default connection opens a popup for the OTP step.

- React
- Vue
- JavaScript
- React Native
- Android
- iOS
- Flutter
- Unity

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'
import { useWeb3AuthConnect } from '@web3auth/modal/react'

const { connectTo } = useWeb3AuthConnect()

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'
import { useWeb3AuthConnect } from '@web3auth/modal/vue'

const { connectTo } = useWeb3AuthConnect()

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'

await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, useWeb3AuthConnect } from '@web3auth/react-native-sdk'

const { connectTo } = useWeb3AuthConnect()

await connectTo({
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
val response = web3Auth.connectTo(
    LoginParams(
        AuthConnection.EMAIL_PASSWORDLESS,
        loginHint = "user@example.com"
    )
)

```

```
let response = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .EMAIL_PASSWORDLESS,
        loginHint: "user@example.com"
    )
)

```

```
final response = await Web3AuthFlutter.login(
  LoginParams(
    loginProvider: Provider.email_passwordless,
    extraLoginOptions: ExtraLoginOptions(
      login_hint: 'user@example.com',
    ),
  ),
);

```

```
var options = new LoginParams
{
    loginProvider = Provider.EMAIL_PASSWORDLESS,
    extraLoginOptions = new ExtraLoginOptions
    {
        login_hint = "user@example.com"
    }
};

web3Auth.login(options);

```

### Custom connection in the modal

Add the Auth Connection ID from the dashboard to `loginMethods`. The email or phone field and OTP stay inside the modal instead of a popup.

- React
- Vue
- JavaScript

```
import { WALLET_CONNECTORS, WEB3AUTH_NETWORK } from '@web3auth/modal'
import { type Web3AuthContextConfig } from '@web3auth/modal/react'

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: '<AUTH_CONNECTION_ID>',
            },
          },
        },
      },
    },
  },
}

```

```
import { WALLET_CONNECTORS, WEB3AUTH_NETWORK } from '@web3auth/modal'
import { type Web3AuthContextConfig } from '@web3auth/modal/vue'

const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    modalConfig: {
      connectors: {
        [WALLET_CONNECTORS.AUTH]: {
          label: 'auth',
          loginMethods: {
            email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: '<AUTH_CONNECTION_ID>',
            },
          },
        },
      },
    },
  },
}

```

```
import { Web3Auth, WALLET_CONNECTORS, WEB3AUTH_NETWORK } from '@web3auth/modal'

const web3auth = new Web3Auth({
  clientId: 'YOUR_WEB3AUTH_CLIENT_ID',
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  modalConfig: {
    connectors: {
      [WALLET_CONNECTORS.AUTH]: {
        label: 'auth',
        loginMethods: {
          email_passwordless: {
              name: 'email passwordless login',
              authConnectionId: '<AUTH_CONNECTION_ID>',
            },
        },
      },
    },
  },
})

```

### Custom implicit flow

When you bypass the modal, pass the same Auth Connection ID together with `login_hint`.

- React
- Vue
- JavaScript
- React Native
- Android
- iOS
- Flutter
- Unity

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'
import { useWeb3AuthConnect } from '@web3auth/modal/react'

const { connectTo } = useWeb3AuthConnect()

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  authConnectionId: '<AUTH_CONNECTION_ID>',
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'
import { useWeb3AuthConnect } from '@web3auth/modal/vue'

const { connectTo } = useWeb3AuthConnect()

await connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  authConnectionId: '<AUTH_CONNECTION_ID>',
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, WALLET_CONNECTORS } from '@web3auth/modal'

await web3auth.connectTo(WALLET_CONNECTORS.AUTH, {
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  authConnectionId: '<AUTH_CONNECTION_ID>',
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
import { AUTH_CONNECTION, useWeb3AuthConnect } from '@web3auth/react-native-sdk'

const { connectTo } = useWeb3AuthConnect()

await connectTo({
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  authConnectionId: '<AUTH_CONNECTION_ID>',
  extraLoginOptions: {
    login_hint: 'user@example.com',
  },
})

```

```
val response = web3Auth.connectTo(
    LoginParams(
        AuthConnection.EMAIL_PASSWORDLESS,
        loginHint = "user@example.com",
        authConnectionId = "<AUTH_CONNECTION_ID>"
    )
)

```

```
let response = try await web3Auth.connectTo(
    loginParams: LoginParams(
        authConnection: .EMAIL_PASSWORDLESS,
        loginHint: "user@example.com",
        authConnectionId: "<AUTH_CONNECTION_ID>"
    )
)

```

```
final response = await Web3AuthFlutter.login(
  LoginParams(
    loginProvider: Provider.email_passwordless,
    // Configure loginConfig with your Auth Connection ID during initialization.
    extraLoginOptions: ExtraLoginOptions(
      login_hint: 'user@example.com',
    ),
  ),
);

```

```
var options = new LoginParams
{
    loginProvider = Provider.EMAIL_PASSWORDLESS,
    extraLoginOptions = new ExtraLoginOptions
    {
        login_hint = "user@example.com"
    }
};

web3Auth.login(options);

```

## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting")

If OTP or magic link emails do not arrive, the recipient may have unsubscribed from Embedded Wallets transactional email. See [Email OTP or magic link not received](/embedded-wallets/troubleshooting/email-otp-not-received/)for the resubscribe form and other checks.
