How to Authenticate Users in Next.js with Asgardeo

Dimuthu Kasun
Identity Beyond Borders
8 min readJan 16, 2022

Next.js is an open-source React web development framework built top on Node.js. NextJS framework is known for,

  • Very SEO-friendly
  • Fast time-to-market
  • Develop applications with Server-Side-Rendering, Static-Site-Generation,
    Client-Side-Rendering and Incremental-Stastical-Regeneration easily.

In this article, I will explain how to do the user authentication in a Next.js application with Asgardeo with help of the NextAuth.js library. NextAuth is an open-source authentication solution for next.js applications. you can find more details about NextAuth.js below.

To demonstrate NextAuth.js integration and user authentication flow with Asgardeo, I will use my existing Next.js application below.

You can find the Next.js template I have used to create the above sample application below.

This application only contains one page as the landing page and it does not have the NextAuth.js integrated. Also, I will use this for demonstration purposes and to be effective, you can use the above sample Next.js application to follow the steps in this article.

the landing page of the sample application

1. Create a Standard-Based application in the Asgardeo console

We need to create a standard-based application in Asgardeo as it is required to initiate authentication flow with Asgardeo using authorization_code grant type.

  • Go to the Asgardeo console and create a standard-based application.
  • Enter a name for the application and select OAuth2.0 OpenID Connect as the protocol. Click Register.
  • You will be redirected to the application page. you can find the client_id and client_secret from the protocol tab.
  • Select code from the Allowed grant types list as we need authorization code grant for the authentication flow.
  • Add below callback URL as Authorized redirect URL to the application. More information about this callback URL can be found here.
http://{host}/api/auth/callback/asgardeo
Eg: http://localhost:3000/api/auth/callback/asgardeo
  • Click on the Update button at the bottom of the page.

2. Integrate NextAuth.js into our Next.js application

Hope you have set up the sample application I have mentioned earlier. As we are using the NextAuth.js library for our authentication purposes, we need to integrate it with our application.

  • Install next-auth dependency. Go to the project directory and run one of the commands below.
yarn add next-auth or npm i next-auth
  • Append the following properties to .env.local file. ClientID and ClientSecret can be found from the protocol tab of the application page in the Asgardeo console that we created in the first step. (the internal_login scope is required to invoke the SCIM /Me endpoint which I will use in this application)
ASGARDEO_CLIENT_ID=<client_id_of_the_appliaction>
ASGARDEO_CLIENT_SECRET=<client_secret_of_the_appliaction>
ASGARDEO_SCOPES=openid email profile internal_login
ASGARDEO_ORGANIZATION_NAME=<organization_name>
  • Create a file [...nextauth].tsx in /pages/api/auth directory. This file contains all global NextAuth.js configurations. All the requests that come to /api/auth/* (sign in, signout requests) will be handled by NextAuth.js

Providers: This is the place we need to configure all the identity providers that we going to use in our application. Of course, this is the place we need to configure Asgardeo :). Currently, we need to configure Asgardeo as a custom provider and Asgardeo will be an inbuilt provider in NextAuth.js in near future.

More about custom providers can be found below.

Callbacks: We can use callbacks to control what needs to happen when some action is performed (sign in, sign out). We can use session, jwt callbacks to retrieve access_token, id_token from the Account model. Account model can use to get information about OAuth accounts associated with a user.

As you can see, in the above code snippet what I have done is attach accessToken, IdToken values with session callback which retrieved from account object in jwt callback.

If you are interested, you can find more information about callbacks, models at the below links.

  • Congrats, you have successfully integrated NextAuth.js with our Next.js application. And the most important thing is we can do user authentication with Asgardeo now :).

3. Implement SignIn, SignOut, API invocation

  • Implement “Login with Asgardeo” Button functionality

Open /components/header/index.tsx file and add Login button onClick event functionality as below.

import { signIn } from "next-auth/react"<Button
onClick={(e) => {
e.preventDefault()
signIn("asgardeo", { callbackUrl: "/home" })
}}
primary>
Login with Asgardeo
</Button>

Here, we can initiate sign-in flow by simply calling signIn method in NextAuth.js.

When calling the signIn() method with no arguments, you will be redirected to the NextAuth.js sign-in page which lists all the providers you have configured. If you want to skip that and get redirected to authenticate with specific provider's immediately, call the signIn() method with the provider's id. In here id will be asgardeo .

Enter the callbackUrl argument and NextAuth will automatically be redirected to that path once signIn flow is successfully completed. I have added /home path as callbackUrl . The next step would be to implement our home page.

  • Implement Home page

Create the file home.tsx in /pages directory. As you may know, Next.js has a file-system-based router built on the concept of pages. So the route for our home page will be /home .

getServerSideProps: This is the asynchronous function that we can export to enable server-side rendering in the Next.js application. Next.js will pre-render this page on each request using the data returned by getServerSideProps. Here I have returned session and organization name values as props.

  • Why use the session that is returned by getServerSideProps?
    - If you refresh the home page from a browser, and if you use usesession() hook for retrieve session, it will pop up an error. With the session returned by getServerSideProps it will always assign value for the session on every request before rendering the page.
  • why we use the value of org instead of directly accessing process.env.ASGARDEO_ORGANIZATION_NAME from the client-side?
    - If we need to access variables on the client-side in Next.js, we need to configure them in next.config.js file. By adding the variables to next.config.js you've exposed the secrets to the client-side. Anyone can see these secrets. As the organization name can vary from environment to environment and also it would be better to store all the variables in one place I chose to store them in env.* .
    The next problem is that we can’t access the variables in the env.* file from the client-side in Next.js using process.env.ASGARDEO_ORGANIZATINO_NAME . So we need to access it from the server-side and pass it to the client-side.
  • Implement SignOut functionality.

As you can see in the created home page above(/pages/home.tsx), following is the Logout button onClick event functionality.

import { signOut } from "next-auth/react"<Button
onClick={(e) => {
e.preventDefault()
signOut({ callbackUrl: "/" })
}}
primary>
Logout
</Button>

Here, we can initiate signOut flow by simply calling signOut method in NextAuth.js.

When calling the signOut() method with no arguments, definitely the session will be deleted and it won’t be redirected to any page and it will stay in the same path(`/home`). with specifying the callbackUrl, you will be redirected to the entered callback URL after the session is deleted.

  • Invoke SCIM2 /Me Endpoint

We can invoke SCIM2 API endpoints in Asgardeo using the accessToken returned after successful login.

AccessToken is stored in the Account model object and with the callbacks that I have implemented in [...nextauth].tsx ,we can access them via session as below.

export default function Page({ session,org }) {const { accessToken, idToken } = session}export async function getServerSideProps(context) {
return {
props: {
session: await getSession(context), org:process.env.ASGARDEO_ORGANIZATION_NAME
}
}
}

Now, we can invoke SCIM2 /Me endpoint with this accessToken.

const res = fetch("https://api.asgardeo.io/t/"+org+"/scim2/Me", {                method: 'get',
headers: new Headers({
"authorization": "Bearer " + accessToken
})
})
.then(r => r.json().then(data => ({
status: r.status, body: data })))
.then(res => {
console.log("API Response"+JSON.stringify(res))
})

4. Run the Application

So far, we have completed,

— Create a standard-based application in Asgardeo console
— NextAuth.js Integration with our Next.js application
— Configure Asgardeo as a provider in NextAuth.js
— SignIn flow
— SignOut flow
— API Invocation

Finally, We have one remaining task. That is to run our application :).

yarn dev or npm run dev

Open the application by accessinghttp://localhost:3000 on the browser and log in to the application using Asgardeo. Make sure to log in using a Customer account(not with an Owner or a Collaborator account) because otherwise, you won’t be able to log in.

More information on user management in Asgardeo can be found below.

home page

Hope you have gained some knowledge on how to authenticate users with Asgardeo in the Next.js application using the NextAuth.js library and how to invoke the Asgardeo APIs with the accessToken with necessary permissions.

You can find the Next.js sample application with all the functionalities described above below.

Thank you for reading this article.

Cheers!

--

--