Skip to content

Setting a password for the embedded wallet

Privy embedded wallets have two core recovery modes: automatic recovery and password-based recovery. At a high-level, this setting modulates how the embedded wallet's recovery share is encrypted and stored.

Privy tip
Automatic and password-based recovery have different tradeoffs between the friction of recovering the wallet on a new device versus the security of having an additional factor (e.g. the password) securing the wallet. Please reach out if you'd like to chat through the best model for your app.

In automatic recovery, Privy encrypts and stores the recovery share of the embedded wallet on behalf of the user. When logging into a new device, users can immediately access their embedded wallet, since Privy will automatically recover it for them behind-the-scenes.

In password-based recovery, users must set a password for the wallet, which Privy uses to encrypt the wallet's recovery share. When logging into a new device, users must enter in their password to recover the wallet on the new device. Once the wallet has been recovered on a device, users will not need to enter their password on that devices again.

By default, Privy secures emebdded wallets with automatic recovery. You can also:

Read below to learn more!

 What does "recovery" refer to?

By design, embedded wallet private keys are created and stored in a client-side environment (the Privy iframe). This is a critical component of the wallet's self-custodial architecture, as it ensures that neither Privy nor app developers can access the wallet's private key.

However, since the private key is never persisted to a server, users must reconstruct their private key in order to use their embedded wallet on a new device. This process is called recovery.

During recovery, Privy combines the auth share of the private key, which is gated by the user's authentication status, and the recovery share of the private key to reassemble the private key on a new device. This allows the user to use the wallet on that device, even if they created the wallet on a different device.

See our security guide for more information about the embedded wallet's architecture, recovery, and key splitting.


Configuring password-based recovery by default

To configure Privy to require that users set a password when their wallet is created, set the config.embeddedWallets.requireUserPasswordOnCreate to true.

tsx
<PrivyProvider
    appId='your-privy-app-id'
    config={{
        embeddedWallets: { 
            requireUserPasswordOnCreate: true // Defaults to false
        } 
        ...insertTheRestOfYourPrivyProviderConfig
    }}
>
    {children}
</PrivyProvider>

WARNING

If a user sets a password for their wallet and loses both their password and their device, their embedded wallet will be unrecoverable even if they still have access to their auth method. This is a key aspect of self-custodial recovery.


In kind, if you plan to have users set passwords for their wallets, we recommend that you make it expressly clear in your app's language that passwords must be securely stored lest wallets become unrecoverable.

Manually setting a password later

You can also opt to have users start with automatic recovery of their wallet for a simpler user experience, and only prompt them to set a password for password-based-recovery later (e.g., when their balance crosses a certain threshold).

TIP

We strongly recommend you prompt users to set a password if their embedded wallets reach a certain usage or asset threshold. This is especially important if you are enabling SMS-based authentication for US users, where SIM swapping is common.


With password-based recovery, even if a user's phone number (or authentication method generally) is compromised, their embedded wallet cannot be accessed on a new device without knowledge of the password.

To prompt users to add a password to their wallet, use the setWalletPassword method from the usePrivy hook.

tsx
const {setWalletPassword} = usePrivy();

This method will open a modal where the user can set a password for their embedded wallet.

When invoked, setWalletPassword will return a Promise for the embedded wallet's updated Wallet object, that will resolve once the user has successfully set a password for their wallet.

The method will reject with an error if the user does not have an embedded wallet, or if the user has already set a password for their wallet. To determine if a user's embedded wallet is already secured by a password, check if the embedded wallet's entry in the user.linkedAccounts array has a recoveryMethod of 'user-passcode'.

tsx
const {user} = usePrivy();
const embeddedWallet = user.linkedAccounts.find(
  (account) => account.type === 'wallet' && account.walletClientType === 'privy',
);
const alreadyHasPassword = embeddedWallet.recoveryMethod === 'user-passcode';

As an example, you might add setWalletPassword as an event handler for a set password button in your app:

tsx
import {usePrivy} from '@privy-io/react-auth';

// This example assumes you have already checked that Privy is `ready` and the user is `authenticated`
function AddPasswordButton() {
  const {user, setWalletPassword} = usePrivy();
  // This is taken from the code snippet above
  const embeddedWallet = user.linkedAccounts.find(
    (account) => account.type === 'wallet' && account.walletClientType === 'privy',
  );
  const alreadyHasPassword = embeddedWallet.recoveryMethod === 'user-passcode';

  return (
    <button
      // Only users who have an embedded wallet and have not already set a password can click
      disabled={!embeddedWallet || !alreadyHasPassword}
      onClick={setWalletPassword}
    >
      Add a password to your wallet
    </button>
  );
}

Once a user has set a password for their wallet, they will only be prompted to re-enter that password when using the wallet on a new device or browser. Once the wallet is recovered on a given device, the user will not need to re-enter their password on that same device.

INFO

Once a password has been set for a wallet, it is not currently possible to reset the password. We are actively building support for this flow.