Estimated integration time: 30 minutes
This guide will show you how to integrate NextAuth and Crossmint in just a few minutes. No pre-requisites.
At the end of this guide you will be able to:
- Allow users to sign up to your website using any social log-in method.
- Create invisible wallets for them upon sign-up.
Setting up a Crossmint account
- Create a Crossmint production (https://www.crossmint.com/console) or staging account (https://staging.crossmint.com/console).
- On the console, get your Wallet API keys (server-side). You will need at least wallets.create, wallets.read, and wallets:nfts.read. Also grab wallets:nfts.transfer if you want to allow users to transfer their NFTs to other wallets.
- Copy your API key (secret) and project ID
Setting up a NextAuth account
First, import NextAuth into your database by following this guide.
Once you’re done, you must enable callbacks so you can create and fetch wallets for a user after they’ve managed to successfully authenticate.
In your […nextauth].js file, ensure jwt is enabled in the session and add 3 callbacks (signIn, jwt, and session).
Here’s some sample code of the […nextauth].js file which implements Google sign-in:
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 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");
}
}
}
For this code to run, you will need to set up some environment variables:
CROSSMINT_X_CLIENT_SECRET: API Key from the Crossmint console (step 3 in set up)
CROSSMINT_X_PROJECT_ID: Project ID from the Crossmint console (step 3 in set up)
CROSSMINT_BASEURL: Use either "https://www.crossmint.com" or
"https://staging.crossmint.com", depending on whether you are running in production
or staging
And that’s it! You can retrieve users’ wallets by running:
const { data: session } = useSession();
if (session == null) {
return;
}
const { wallets } = session;
Check Crossmint’s documentation for many more things you can do with Crossmint.