NextJS 13 / React Single Sign-On (SSO) Authentication Via Azure Active Directory (AD)

Jay @ Designly - Mar 8 '23 - - Dev Community

SSO stands for Single Sign-On, which is a method of authentication that allows users to access multiple applications or systems using a single set of login credentials.

With SSO, users don't have to remember separate usernames and passwords for each application or system they use, which can be a significant advantage, especially when working with numerous applications.

The SSO process typically works as follows:

  1. The user logs in to a central identity provider (IDP) with their username and password.
  2. The IDP authenticates the user's credentials and issues a security token.
  3. When the user attempts to access another application, the application requests authentication from the IDP.
  4. The IDP verifies the user's identity using the security token and grants access to the application.

There are several benefits of using SSO, including:

  1. Increased security: SSO reduces the need for users to remember multiple login credentials, which can lead to weak passwords or password reuse. Also, SSO helps with the centralized management of user access and authentication policies.
  2. Improved user experience: SSO simplifies the login process, saving time and effort for users. Also, users can easily access multiple applications with a single set of credentials.
  3. Reduced IT overhead: With SSO, IT administrators can manage user access and authentication policies centrally, reducing the need for separate user account management for each application.

Undoubtedly, one of the most popular IDPs is Microsoft Azure AD. Why, you ask? One reason: Windows. Corporate users expect their corporate login credentials to be able to access everything corporate related. And they should! And Microsoft Azure makes it possible. With Azure, you can sync your local AD domain users in the cloud. Once everything is synced, you can register an OAUTH app to log user's in to your web app just like "Log In With Facebook." Cool huh?

In this tutorial, I'll show you how to authenticate a user against an Azure AD domain in a NextJS 13 app environment. This tutorial assumes that you've already created your app using npx create-next-app.

We're going to use a library called next-auth to handle our complete authentication flow. Next-Auth is a complete authentication library that aggregates several identity providers and standardizes the user object obtained from each provider to greatly simplify your code. To install, just run npm i next-auth.

Before we get to coding, you're going to need to register your app in Azure AD. I'm going to assume that you already have a MS Azure account and an Active Directory Domain.

From the Azure Console, navigate to Azure Active Directory. From the left sidebar, choose App registrations, and then click New registration from the top menu bar:

Create new registration

Choose a customer-facing display name for your app (e.g. ACME Corp Intranet), then select "Default Directory only Single-Tenant", unless you have more than one AD tenant and you want to be able to sign-in against any of them. Finally, for redirect URI, choose "Web" and then enter http://localhost:3000/api/auth/callback/azure-ad. Note that you can only have one callback URI here, so you'll need to change it to the production value when ready to deploy your app. Alternatively, you could create two app registrations, one for development, and one for production.

Create new registration

After clicking Register, you should get a confirmation screen. Copy the Client ID and Tenant ID to a text file and then click Add a certificate or secret.

Copy credentials

On the Certificate & secrets screen, click the + New client secret button on the top menu bar, enter a description (e.g. web app) and choose 180 days for expiration (unless you have a reason to make it shorter), then click Add. Once created, copy the Value to your credentials text file.

Copy credentials

That's it for configuration in Azure AD. Next, you'll need to create three environment variables for the three values you copied:

NEXT_PUBLIC_AZURE_AD_CLIENT_ID=f82a80c3-e18f-4947-b3df-349e2945c58d
NEXT_PUBLIC_AZURE_AD_TENANT_ID=f7d2c8c2-77d9-4999-971b-756caf274c26
NEXT_PUBLIC_AZURE_AD_CLIENT_SECRET=uqf8Q~FX2DHkdI3zkQRAgYVg-cQrDu.ZrH9Zqdbi
Enter fullscreen mode Exit fullscreen mode

Next, we'll need to create an API route for authentication and register Azure AD as a provider:

// @/pages/api/[...nextauth].js

import NextAuth from "next-auth"
import AzureADProvider from "next-auth/providers/azure-ad"

export const authOptions = {
    providers: [
        AzureADProvider({
            clientId: process.env.NEXT_PUBLIC_AZURE_AD_CLIENT_ID,
            clientSecret: process.env.NEXT_PUBLIC_AZURE_AD_CLIENT_SECRET,
            tenantId: process.env.NEXT_PUBLIC_AZURE_AD_TENANT_ID,
            name: "ACME Corp Login",
        }),
    ],
}

export default NextAuth(authOptions)
Enter fullscreen mode Exit fullscreen mode

Note that we're using a dynamic route for the file name. This is because we can specify multiple providers in this one file. For a full list of providers, follow this link.

Finally, we must wrap our app component in our next-auth provider context:

// @/pages/_app.js

import '@/styles/globals.scss'
import { SessionProvider } from "next-auth/react"

export default function App({
  Component,
  pageProps: { session, ...pageProps }
}) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode

That's it! Now you can sign users in via /api/auth/sign-in, and sign out with /api/auth/sign-out. You can also access the useSession hook anywhere within your code, client or server-side.

Example:

// @/components/Layout/AuthLayout.js

import React from 'react'
import Head from 'next/head'
import MenuBar from './MenuBar'
import LoginScreen from '../Auth/LoginScreen'

import { useSession } from "next-auth/react"

export default function AuthLayout({ children, title }) {
    const { data: session } = useSession();
    console.log(session)

    let titleConcat = "ACME Corp Intranet";
    if (title) titleConcat += " | " + title;

    if (session) {
        return (
            <>
                <Head>
                    <title>{titleConcat}</title>
                </Head>
                <main className="h-screen bg-bg text-white/90">
                    <header className="mb-10">
                        <MenuBar />
                    </header>
                    <div className="flex flex-col">
                        {children}
                    </div>
                </main>
            </>
        )
    } else {
        return <LoginScreen />
    }
}
Enter fullscreen mode Exit fullscreen mode

Thank you for taking the time to read my article and I hope you found it useful (or at the very least, mildly entertaining). For more great information about web dev, systems administration and cloud computing, please read the Designly Blog. Also, please leave your comments! I love to hear thoughts from my readers.

I use Hostinger to host my clients' websites. You can get a business account that can host 100 websites at a price of $3.99/mo, which you can lock in for up to 48 months! It's the best deal in town. Services include PHP hosting (with extensions), MySQL, Wordpress and Email services.

Looking for a web developer? I'm available for hire! To inquire, please fill out a contact form.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player