[Optional] Set Up Authentication
Crossmint wallets work with your existing authentication or directly with preferred auth partners.
If you're creating wallets for your users, you will need a way to securely authenticate a given user so that they (and only them) can have access to their resources. In this guide, we explain how you can connect Crossmint wallet APIs to an existing auth solution, or build one from scratch in minutes by using pre-made sample code with leading auth providers such as Stytch, Firebase, Auth0 or Dynamic.xyz.
Getting Started with Stytch
For this authentication method we’ve built an open source repository to get started with Crossmint’s Stytch style integration.
In this guide you will learn how to:
- Set up Stytch authentication in your app.
- Create Crossmint wallets attached to Stytch users on any supported chain.
Repository Setup:
- Download the
stytch-crossmint
repository - Open the project in your favorite IDE.
- In the root directory of the project, rename the file called
.env.template
to.env.local
. You'll be filling out this file throughout the setup process.
Stytch Setup:
- Create a Stytch account.
a. When prompted between “Consumer Authentication” and “B2B Authentication, select the “Consumer Authentication” option. - Navigate to Frontend SDKs on the side-bar.

a. Select Test environment (should be the default option).
b. Click the Enable SDK button and confirm the prompt. This will create your Stytch API keys.
- Add an authorized environment:
a. Click on the “+ Add” button
b. Add your site/vercel or local domain to be authorized.
c. Click "Save".

- Adding your API Keys to the project.
a. Go to API Keys in the Configuration section
b. Select the Test environment and copy the Public Token located at the bottom of the page.
Should look like this:

c. In the crossmint-stytch
project, paste the copied value for the variables:
NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN
STYTCH_PROJECT_ID
STYTCH_SECRET
into the .env.local
file
Example: NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN=public-token-test-xxxxx…
Crossmint Setup:
Now you need to sign up in Crossmint and create an API key that allows you to create and manage wallets for your users. During development, you’re going to create wallets in Crossmint’s staging sandbox.
-
Go to staging.crossmint.com/console and sign in / create an account.
-
Go to API keys and create a New API Key with scope for
wallets.read
andwallets.create
.


Finally save your new key and copy the CLIENT SECRET
and Project ID
values for later.
- In the
crossmint-stytch
project, set the value of the following three keys in the.env.local
file:
- CROSSMINT_BASEURL
- CROSSMINT_X_CLIENT_SECRET
- CROSSMINT_X_PROJECT_ID
Example:
CROSSMINT_BASEURL=https://staging.crossmint.com
CROSSMINT_X_CLIENT_SECRET=sk_test.xxxxxx
CROSSMINT_X_PROJECT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Once entered, save the file.
Reminder
Crossmint wallet APIs are server-side ONLY. Make sure your client secret doesn't get leaked, as it would allow others to create wallets and manage assets for your users.
Running the Project Locally
Run the following command to get the project up and running:
yarn dev
You can view your locally hosted site on http://localhost:3000
Troubleshooting
- User already has something running on port 3000, so this app opens on 3001.
"error_message":"public_token_id format is invalid."
- Help URL: https://stytch.com/docs/api/errors/400#invalid_public_token_id
- Public token is at the bottom of API keys page. Make sure your token starts with:
public-token-test
"error_type":"no_match_for_provided_magic_link_url"
Help URL: https://stytch.com/docs/api/errors/400#no_match_for_provided_magic_link_url
Getting Started with Auth0
Auth0 is a much more seamless integration without having the worry of having any additional api routes on your server.
Setting up Auth0:
To get started, authenticate with Auth0 and on the Getting Started page, click on "Create Application"

In this example, we'll be using a Single Page Web Application

Once selected, click on "Create" and you'll be navigated to your application page. On this page, select "Settings"

Inside of the settings page, you can see all of your API keys that you'll need to use under "Basic Information".
Here are the values you'll need:
- Domain
- Client ID
- Client Secret
Adding Crossmint Action
On the left-side tab, go to Actions->Flows

Under flows, select Login

Add an action by browsing the marketplace

Select the Crossmint Action

Click on Add Integration

Follow the remaining steps presented on screen.
Getting started with NextAuth
NextAuth allows you to be in full control of authentication, letting you select which auth providers you'd like to use, control over jwt storage and more!
To get started, begin by following this guide from NextAuth to configure your repo to use NextAuth. Once you've got that setup, we can move on to the integration steps.
Configuring NextAuth with Crossmint
In order to use Crossmint wallets with NextAuth, we need to enable some callbacks so that we can create and fetch wallets for a user after they've managed to successfully authenticate.
In your [...nextauth].js
file, we want to ensure jwt
is enabled in our session and add 3 callbacks (signIn
, jwt
, and session
).
Here's some sample code of our [...nextauth].js
file using Google OAuth:
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import { WalletService } from "@/services/wallets";
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET
})
],
session: {
jwt: true,
},
callbacks: {
async signIn({ user, isNewUser }) {
if (isNewUser) {
console.info(`NextAuth: created user ${user.id}`);
await WalletService.createWallets(user.id);
console.info(`NextAuth: initialized wallet for user ${user.id}`);
}
console.info(`NextAuth: fetching wallets for user ${user.id}`);
user.wallets = await WalletService.fetchWallets(user.id);
return true;
},
async jwt({ token, user, account, profile, isNewUser }) {
if (user) {
token.wallets = user.wallets;
}
return token;
},
async session({ session, token }) {
session.wallets = token.wallets;
return session;
},
}
}
export default NextAuth(authOptions);
We'll also need to add the wallets service which will be used for creating/fetching the wallets:
Here's our service file which just uses 2 api endpoints (Creating a wallet and Fetching your wallets)
export class WalletService {
static async fetchWallets(userId) {
let walletsMap = {};
const existingWallets = await WalletService.#fetchWalletsInternal(userId);
existingWallets.forEach((wallet) => {
const chain = wallet.chain;
const address = wallet.publicKey;
walletsMap[chain] = address;
});
return walletsMap;
}
static async createWallets(userId) {
const url = `${process.env.CROSSMINT_BASEURL}/api/v1-alpha1/wallets`;
const options = WalletService.#createOptions(
"POST", { chain: "ethereum", userId: userId });
return WalletService.#fetchWithExceptionHandling(url, options);
}
static async #fetchWalletsInternal(userId) {
const url = new URL(`${process.env.CROSSMINT_BASEURL}/api/v1-alpha1/wallets`);
url.searchParams.append('userId', userId);
const options = WalletService.#createOptions("GET");
return WalletService.#fetchWithExceptionHandling(url, options);
}
static #createOptions(method, body = null) {
return {
method: method,
headers: {
accept: "application/json",
"X-CLIENT-SECRET": process.env.CROSSMINT_X_CLIENT_SECRET,
"X-PROJECT-ID": process.env.CROSSMINT_X_PROJECT_ID,
...(body && { "content-type": "application/json" })
},
...(body && { body: JSON.stringify(body) })
};
}
static async #fetchWithExceptionHandling(url, options) {
try {
const response = await fetch(url, options);
return await response.json();
} catch (error) {
console.error("Error whilst fetching", error);
throw new Error("An internal error has occurred");
}
}
}
With this, you're done and now can start using the wallet values!
Using Wallets from NextAuth:
Here's how you would get the wallets once a user has successfully authenticated on your platform:
const { data: session } = useSession();
if (!session) {
return;
}
const { wallets } = session;
Updated about 1 month ago