Next Auth
This page will show you how to integrate Auth with NextAuth to let your users login with their wallets.
More specifically, we'll show you how to use our ThirdwebAuthProvider which is fully compatible with standard NextAuth providers to add support for thirdweb Auth to your apps.
If you want to interact with a working version of the Auth + NextAuth integration that we'll be building in this guide, you can checkout the following GitHub repository, or clone it with the command below:
npx thirdweb create app --template thirdweb-auth-next-auth
Getting Started
To add Auth + NextAuth to your application, you'll need to install the @thirdweb-dev/auth and @thirdweb-dev/react packages and the ethers peer dependency, along with the actual next-auth package itself:
Now, we can configure the ThirdwebAuthProvider on our NextAuth API routes to add support for wallet based login, in addition to all other existing authentication methods. The ThirdwebAuthProvider uses NextAuth's Credentials Provider underneath to enable custom wallet based authentication (for those curious to dig deeper, you can take a look at the ThirdwebAuthProvider implementation).
Here, we configure the ThirdwebAuthProvider with a domain coming from NEXT_PUBLIC_THIRDWEB_AUTH_DOMAIN environment variable, which we can set in the .env.local file as follows:
The domain is used to prevent phishing attacks when your users login with their wallets - you can learn more about this in the how auth works documentation.
It's important to note that we created the authOptions as a separate object which we exported from the file - we'll use these options later to authenticate the user on the server-side.
Additionally, we pass the authSession callback function to the session callback of NextAuth. This is used to ensure that we always extract the wallet address of the logged in user to expose it on the session object for the client and server to access. We'll discuss custom usage of this function more in later sections.
Then, on the frontend, we first need to configure the necessary SessionProvider and ThirdwebProvider in our pages/_app.tsx file to be able to use Auth:
With this setup, we can now use the useAuth hook and NextAuth's signIn function to login the user with their wallet:
Here, we use the useMetaMask and useAddress to let the user connect their wallet and get the address of the connected wallet on the client. Then, we use the loginWithWallet function to log th user into the backend, and the user will then be accessible via the useSession hook.
Usage
Authenticating the user on the server
NextAuth's getServerSession function can be used to authenticate the user on the server. It will return the active session data if the user is logged in, or null if the user is not authenticated.
In order to use this function, we need to pass in the incoming request and response objects, as well as the authOptions that we previously configured in our next-auth file.
It can be used in any server-side context, including in Next.js API routes, as well as server-side functions like getServerSideProps and getStaticProps.
If the user is logged in with their wallet (via the ThirdwebAuthProvider), then the session.user.address value will be exposed to read the wallet address of the logged in user:
Validating the login request
By default, the Auth API will validate the login request by checking that the user requesting to login successfully signed a valid sign-in with wallet message. However, this doesn't perform specific checks on the exact contents of the payload, aside from the domain used for anti-phishing.
If you want to add specific checks to enforce the exact data on the login payload signed by users, you can use the authOptions configuration on the ThirdwebAuthProvider:
Note that when you enforce these checks on the server-side, you'll also want to pass in the proper parameters to the login function on your client-side application to ensure that the login payload gets the correct format. You can see an example of how to do this in the React section.
Prevent replay attacks
Since the sign-in with wallet payload is used to login to your server, it's important to prevent third parties from being able to reuse old login payloads to falsely authenticate as other users. This reuse of old login payloads is called a replay attack.
Luckily, all sign-in with wallet payloads include a nonce field which is a random string generated when the request was created. If you are using a database, or have somewhere to store nonces, you can ensure that each nonce is only used once:
Add custom logic to the session callback
By default, you can pass the authSession function straight to the session callback, but in some cases you may want to add your own custom logic into the session callback. In this case, you can wrap the authSession function as follows:
Getting proper user types for TypeScript
By default, TypeScript won't know about the session.user.address field that's populated onto the user object and available through the useSession and getSession functions, so it will give you type errors if you try to access that value, even if it's defined. To solve this, you can override the type for the Session object by creating a next-auth.d.ts file in your project root: