Docs

Wallet Configuration

Auth makes use of a server-side wallet to sign and verify JWTs, as covered in the how auth works section. You can configure this wallet using a variety of wallet management options, giving you the freedom to choose the most convenient and secure setup for your project.

Simple Wallets

The easiest way to get started with Auth would be to use a simple private key or signer wallet directly. It's easy to use such a setup with just the core @thirdweb-dev/auth package.

Setup

Use the following installation to get started with Auth using a simple EVM private key or signer wallet:

npm install @thirdweb-dev/auth ethers@5

Private Key Wallet

You can use an EVM private key (a 64 character hex-string) as your wallet by using the PrivateKeyWallet class from the @thirdweb-dev/auth/evm entrypoint.

import { PrivateKeyWallet } from "@thirdweb-dev/auth/evm";

// Pass private key from environment variables directly
const wallet = new PrivateKeyWallet(
  process.env.THIRDWEB_AUTH_PRIVATE_KEY || "",
);

// Pass the wallet to your auth configuration...

Signer Wallet

You can also use any signer wallet compatible with the ethers.Signer interface, such as the ethers.Wallet class.

import { SignerWallet } from "@thirdweb-dev/auth/evm";
import { ethers } from "ethers";

// Create a new ethers signer or use an existing one
const signer = new ethers.Wallet(...);
const wallet = new SignerWallet(signer);

// Pass the wallet to your auth configuration...

Advanced Wallets

For more advanced wallet setups like cloud wallets, managed private keys, and more, we have a variety of options available in our @thirdweb-dev/wallets package. The package is an optional peerDependency of @thirdweb-dev/auth, so you'll need to install it separately, along with any peer dependencies of the specific wallet you want to use.

npm install @thirdweb-dev/auth @thirdweb-dev/wallets

For more information on the available wallets and the specific of their setup, see the @thirdweb-dev/wallets documentation

For example, here's how you would use a signing key from AWS Secrets Manager as your Auth wallet using the @thirdweb-dev/wallets package (you would need to install its @aws-sdk/client-secrets-manager peer dependency as well):

import { AwsSecretsManagerWallet } from "@thirdweb-dev/wallets/evm/wallets/aws-secrets-manager";

// Pass in your AWS configuration
const wallet = new AwsSecretsManagerWallet({
  secretName: "my-secret",
  secretKeyName: "private-key",
  awsConfig: {
    region: "us-east-1",
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID || "",
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || "",
    },
  },
});

// Pass the wallet to your auth configuration...

Custom Wallets

If none of the above methods are suitable for your project, you can also create your own custom wallet class by implementing the GenericAuthWallet interface from the @thirdweb-dev/wallets package for a completely custom setup.

Auth only requires the following simple wallet interface to facilitate signing and verification of JWTs:

interface GenericAuthWallet {
  // Get the address of your wallet
  getAddress(): Promise<string>;
  // Optionally get the chain ID of your wallet (important for EIP1271 wallets)
  getChainId?(): Promise<number>;
  // Sign a message with your wallet
  signMessage(message: string): Promise<string>;
  // Verify a signature
  verifySignature(
    message: string,
    signature: string,
    address: string,
  ): Promise<boolean>;
}

You can see how this interface is chain agnostic, and can be used across different blockchain ecosystems.

For example, here is a minimal implementation of the basic SignerWallet class from the @thirdweb-dev/auth/evm entry point, which follows the GenericAuthWallet interface:

import type { Ecosystem, GenericAuthWallet } from "@thirdweb-dev/wallets";

class SignerWallet implements GenericAuthWallet {
  type: Ecosystem = "evm";
  #signer: ethers.Signer;

  constructor(signer: ethers.Signer) {
    this.#signer = signer;
  }

  public async getAddress(): Promise<string> {
    return this.#signer.getAddress();
  }

  public async signMessage(message: string): Promise<string> {
    return await this.#signer.signMessage(message);
  }

  public async verifySignature(
    message: string,
    signature: string,
    address: string,
  ): Promise<boolean> {
    const messageHash = ethers.utils.hashMessage(message);
    const messageHashBytes = ethers.utils.arrayify(messageHash);
    const recoveredAddress = ethers.utils.recoverAddress(
      messageHashBytes,
      signature,
    );
    return recoveredAddress === address;
  }
}