Skip to main content

Use a passkey with MetaMask Smart Accounts

Passkeys eliminate the need for traditional seed phrases that are difficult to remember, enabling a more seamless and secure way for users to access their Externally Owned Accounts (EOAs). Compared to traditional EOAs which use secp256k1 elliptic curve to generate key pairs and signatures, a passkey-based EOA uses the secp256r1 (P-256) elliptic curve.

MetaMask Smart Accounts is signer agnostic and natively supports passkeys (P-256 elliptic curve signatures), so you can use a passkey as the signer.

Prerequisites

  • Install Node.js v18 or later
  • Install Yarn, npm, or another package manager

Steps

1. Install dependencies

Install the Smart Accounts Kit and other dependencies in your project:

npm install @metamask/smart-accounts-kit ox

2. Create a passkey

To create a passkey signer, use Viem's createWebAuthnCredential function to securely register the passkey (WebAuthn credential).

import { createWebAuthnCredential } from 'viem/account-abstraction'

const credential = await createWebAuthnCredential({
name: 'MetaMask Smart Account',
})

3. Create a smart account

Once the passkey is created, use the Viem WebAuthn Account to configure your passkey as a MetaMask smart account signer.

The deployParams parameter needs the X and Y coordinates of the P-256 public key. Since WebAuthn credentials store a compressed public key, you need to deserialize it, and extract the X and Y coordinates.

import { publicClient } from "./config.ts"
import { Implementation, toMetaMaskSmartAccount } from "@metamask/smart-accounts-kit";
import { toWebAuthnAccount } from "viem/account-abstraction";
import { Address, PublicKey } from "ox";
import { toHex } from "viem";

const webAuthnAccount = toWebAuthnAccount({ credential });

// Deserialize compressed public key
const publicKey = PublicKey.fromHex(credential.publicKey);

// Convert public key to address
const owner = Address.fromPublicKey(publicKey);

const smartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [owner, [toHex(credential.id)], [publicKey.x], [publicKey.y]],
deploySalt: "0x",
signer: { webAuthnAccount, keyId: toHex(credential.id) },
});

Next steps