Skip to content

Wallet Creation and Recovery

Creating embedded wallets

To create wallets for your users as part of the login flow you need to set the configureEmbeddedSigner. The configure parameter depends on the type of recovery you want to enable in your app. Therefore, it's important to first decide the recovery method of the signer.

Make sure to wait for the embedded state ready before using the embedded wallets. Learn more about how to check the embedded state.

Decide a recovery method

Recovering the embedded wallet is needed when a user logs into a new device or when access to the embedded wallet is lost.

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

  • Automatic recovery: The recovery share is encrypted with a combination of project entropy and Openfort's entropy. When logging into a new device, users can immediately access their embedded wallet.
  • User-based recovery: The recovery share is encrypted by user-provided entropy. When logging into a new device, users must enter in their password to recover the embedded wallet on the new device. Once the embedded wallet has been recovered on a device, users will not need to enter their password on that devices again.

Automatic recovery

It is worth noting that while automatic recovery makes for smooth user UX (without needing to set up a recovery system upfront when logging in), it comes with tradeoffs. Notably, the root of trust with is in the user's authentication token. This means access to the auth token grants access to the wallet. Accordingly, this token must be properly secured at all times.

When using automatic recovery, Shield generates a password that is used for the encryption of the recovery share. The full encryption key can only be accessed if the decryption request includes the user's auth token.

From your backend, you should have an endpoint that generates an encryption session for the user. This endpoint should be protected and only accessible by the user who is requesting the encryption session (i.e. the user who is logging in).

For example, in a Next.js API route, you can create an endpoint like this:

protected-create-encryption-session.ts
import openfort from "./openfortAdminConfig";
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const session = await openfort.registerRecoverySession(
    "YOUR_SHIELD_PUBLISHABLE_KEY",
    "YOUR_SHIELD_SECRET_KEY",
    "YOUR_SHIELD_ENCRYPTION_SHARE"
  );
  res.status(200).send({
    session: session,
  });
}

Once we've secured the backend we setup the client side:

Openfort auth

configure.tsx
import {
  ShieldAuthType,
  ShieldAuthentication,
  RecoveryMethod,
} from "@openfort/openfort-js";
import openfort from "./openfortConfig";
import getEncryptionSession from "./encryptionSession";
 
async function authSetAutomaticRecoveryMethod(email: string, password: string) {
  const response = await openfort.auth.signUpWithEmailPassword({
    email,
    password,
  });
  const chainId = 80002;
  const shieldAuthentication: ShieldAuthentication = {
    auth: ShieldAuthType.OPENFORT,
    token: response.token,
    encryptionSession: await getEncryptionSession(),
  };
  await openfort.embeddedWallet.configure({ chainId, shieldAuthentication });
}

Third party auth

This example will showcase Firebase as the third-party auth provider. You can replace it with any other third-party auth provider.

configure.tsx
import {
  ShieldAuthType,
  ShieldAuthentication,
  ThirdPartyOAuthProvider,
  TokenType,
  RecoveryMethod,
} from "@openfort/openfort-js";
import openfort from "./openfortConfig";
import getEncryptionSession from "./encryptionSession";
 
async function authSetAutomaticRecoveryMethod(idToken: string) {
  await openfort.auth.authenticateWithThirdPartyProvider({
    provider: ThirdPartyOAuthProvider.FIREBASE,
    token: idToken,
    tokenType: TokenType.idToken,
  });
  const chainId = 80002;
  const shieldAuthentication = {
    auth: ShieldAuthType.OPENFORT,
    token: idToken,
    authProvider: "firebase",
    tokenType: "idToken",
    encryptionSession: await getEncryptionSession(),
  };
  await openfort.embeddedWallet.configure({ chainId, shieldAuthentication });
}

User-based recovery

Password recovery

Require that users set a password when the wallet is created, enforcing password-based recovery from the start.

If encrypted by user-provided entropy, only the user can decrypt the recovery share. Openfort never sees the user's password. Therefore, if you're not planning to ever user the automatic recovery mode, you can use the encryption share in the client side of the application.

Openfort auth

configure.tsx
import {
  ShieldAuthType,
  ShieldAuthentication,
  RecoveryMethod,
} from "@openfort/openfort-js";
import openfort from "./openfortConfig";
 
async function authSetPasswordRecoveryMethod(
  email: string,
  password: string,
  recoveryPassword: string
) {
  const response = await openfort.auth.signUpWithEmailPassword({
    email,
    password,
  });
  const chainId = 80002;
  const shieldAuthentication: ShieldAuthentication = {
    auth: ShieldAuthType.OPENFORT,
    token: response.token,
  };
  const recoveryParams = {
    password: recoveryPassword,
    recoveryMethod: RecoveryMethod.PASSWORD,
  };
  await openfort.embeddedWallet.configure({
    chainId,
    shieldAuthentication,
    recoveryParams,
  });
}

Third party auth

This example will showcase Firebase as the third-party auth provider. You can replace it with any other third-party auth provider supported by Openfort or with Custom Auth.

configure.tsx
import {
  ShieldAuthType,
  ShieldAuthentication,
  ThirdPartyOAuthProvider,
  TokenType,
  RecoveryMethod,
} from "@openfort/openfort-js";
import openfort from "./openfortConfig";
 
async function authAndSetPasswordRecoveryMethod(
  idToken: string,
  password: string
) {
  await openfort.auth.authenticateWithThirdPartyProvider({
    provider: ThirdPartyOAuthProvider.FIREBASE,
    token: idToken,
    tokenType: TokenType.idToken,
  });
  const chainId = 80002;
  const shieldAuthentication: ShieldAuthentication = {
    auth: ShieldAuthType.OPENFORT,
    token: idToken,
    authProvider: "firebase",
    tokenType: "idToken",
  };
  const recoveryParams = {
    password: password,
    recoveryMethod: RecoveryMethod.PASSWORD,
  };
  await openfort.embeddedWallet.configure({
    chainId,
    shieldAuthentication,
    recoveryParams,
  });
}

Pregeneration

Openfort also allows you to pre-generate embedded wallets for your users, even before they first login to your app. Please see our pregeneration guide for more.