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: