NextAuth & Dynamic
Pre-requisites
- Cloned the nextAuth example repo and installed dependencies (You can also see the end result after adding Dynamic here).
Steps
Add the right env variables
You’ll need to define two environment variables in your .env.local
file:
You’ll be able to find both in the SDK & API Keys page of the Dynamic dashboard. The first will already be generated for you but for the API key, you’ll need to generate your own via the UI on that page.
Make sure you add the values of each variable to the .env.local
file, and you’re good to go.
Add the Dynamic Provider
We are going to use the Dynamic UI on the client, so the first thing we’ll want to do is add an initialize the DynamicContextProvider and then we can use the DynamicWidget UI.
First make sure you have the appropriate dependencies installed:
Next we will add the provider. Normally you would add the provider to one of your high level component files directly, wrapping everything else but in Next, this will likely cause some client - server issues especially because we’re going to be utalizing callbacks, so we’ll handle this in two ways:
Firstly, we’ll create a file to export what we need from Dynamic and then we’ll import that file in the client side code:
Secondly, we’ll create a wrapper for the provider itself:
Note that we are using only EthereumWalletConnectors, but you can add any of the other connectors you want to use.
Now we can add the wrapper to our layout.tsx
file:
Add the DynamicWidget
You don’t need to add the widget at the same level as the provider, you can place this anywhere. For this example we’ll add it to the header:
Now we’re almost done with the client side. We’ll need to somehow send the JWT that Dynamic returns on login to our server functions so that we can validate it and create a session. To do this we’ll use the events
which Dynamic provides but let’s come back to that and first add the server side code.
Define the JWT decoding
NextAuth needs to know how to decode and validate the JWT which Dynamic sends back. To do this we’ll create a custom JWT decoder inside a new helper file:
You’ll see that the above function depends on a few things, one of which is the external jsonwebtoken library. We’ll need to install this:
Next we’ll need to define the getKey
function which is used to fetch the public key which you can use to decode the JWT. This function will make an API call to Dynamic. We’ll add this to the same file:
With this in place, there are just two steps left. Firstly we’ll need to adapt the NextAuth configuration to use the CredentialsProvider so the JWT works, and then we’ll need to trigger everything correct when a user logs in.
Update the NextAuth configuration
You can copy the below code and paste it over the full existing auth.ts file in the demo repo:
Trigger the JWT validation on login
We’ll need to access the JWT which Dynamic sends back after a user has logged in so that we can co-ordinate with NextAuth. To do this we’ll use one of the events which Dynamic provides. Back in the dynamic-wrapper.ts
file we’ll adjust the settings object passed to DynamicContextProvider as a prop to the following:
Note that we’re using the getCsrfToken
function which NextAuth provides. This is important because NextAuth uses CSRF tokens to prevent CSRF attacks.
Token Scopes
A JWT token supports the concept of scopes, which are used to define the permissions that the token has. Dynamic uses various scopes to identify limitations for a token.
The most common and important scope value is requiresAdditionalAuth
which signifies that the token requires MFA to be completed before the token is considered valid and the user is fully authenticated.
Our SDK handles this for the frontend, but for the backend you will need to check this scope and handle it accordingly.
To do this, you can add a check for the requiresAdditionalAuth
scope in the authorize
function in the auth.ts
file:
Alternatively, you can return null
if you do not want to handle the token with the requiresAdditionalAuth
scope.
Run the example
You should now see a “Connect your wallet” button in the header, which you can use to log in with a wallet etc. Once you’ve logged in you should see “LOGGED IN” in the browser console.
Going further
You’ll see in auth.js that we are assigning certain JWT fields to a user object. You can add any fields you want to this object, and then access them in your pages via the useSession
hook.
Was this page helpful?