Azure AD Authentication using MSAL and Next.js (React)
Tags: nextjs, azure, react, webdev
Published: 2021-07-27 08:23:51

Microsoft Authentication Library (MSAL) for Javascript enables client-side web applications to authenticate users using Azure Active Directory (Azure AD), using security tokens acquired from the Microsoft Identity platform. It is particularly helpful if you want to specify which users can sign in to your application, e.g., your organization or school. You can learn more about it [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-overview).

## App Registration
To get started, we need to register our application in the Microsoft Identity Platform (Azure AD). We will register a single-page application (SPA) and use the recommended authentication flow, **MSAL.js 2.0**, which supports the authorization code flow with PKCE. More on this can be found [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-app-registration).

- Sign in to the [Azure Portal](https://portal.azure.com/)
- Search for and select Azure Active Directory.
- Under **Manage** in the side menu, find and select **App Registration**
  ![App Registration on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5d32w61q5kt06tvwjhe.png)
	 
- Create a **New Registration** and fill in the form by entering the **name** of the app (can be changed later) and selecting the **support account types** (I used the **single-tenant** option, the first option in the screenshot below). **DO NOT** enter a **Redirect URI** for now.
  ![App Registration on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yuf24ypg46gqvfsupzv1.jpg)
  ![App Registration on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7q2fbf5fuaufqk23q15.jpg)

- Select the newly created application and then select **Authentication** > **Add Platform** under the **Manage** menu
  ![Authentication Platform on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cgsgeovefrq782gaoq7.png)
  ![Authentication Platform on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wmwo5z0qcdluq9xhezkq.png)

- Select the **Single-Page Application** tile under the **Web applications** heading
  ![Authentication Platform on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hol7q9sry75k89wqlh3b.png)
  ![Authentication Platform on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsbmk3kbhgb47bszko6l.png)

- Enter a **redirect URI**. I'll be using `http://localhost:3000/`. **DO NOT** check the boxes under **Implicit grant and hybrid flows** heading
- Click on the **Configure** button to finish.
**Note** You can add more than one redirect URI, for instance, for different environments, development, staging, production, etc.

## Installation
Open your terminal and create a Next.js app
```bash
npx create-next-app msal-next-auth --use-npm

cd msal-next-auth
```

The only dependencies that you will need are the MSAL react and browser libraries.
```bash
npm install @azure/msal-react @azure/msal-browser
```

## Initialization
Create a file `services/msal.js` in the root of the project and add the following code
```js
import * as msal from "@azure/msal-browser";

const msalConfig = {
    auth: {
        clientId: process.env.NEXT_PUBLIC_AZURE_AD_CLIENT_ID,
        authority: `https://login.microsoftonline.com/${process.env.NEXT_PUBLIC_AZURE_AD_TENANT_ID}`,
        redirectUri: '/'
    }
};

const msalInstance = new msal.PublicClientApplication(msalConfig);

export { msalInstance }
```

You can find your **CLIENT ID** AND **TENANT ID** in the Azure portal. Select the app you registered and copy and paste the actual values from the Overview page (under Essentials) into an environment variables file, `.env.local`, in the root of the project folder.

`.env.local`
```
NEXT_PUBLIC_AZURE_AD_CLIENT_ID='your-client-id'
NEXT_PUBLIC_AZURE_AD_TENANT_ID='your-tenant-id'
```

![Client and Tenant ID on Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu6mf50sf76rzytjt9mp.png)

We'll be using React's Context API to provide/share the **MSAL** service instance to all our components/pages. To do that, make the following changes to `pages/_app.js`

```jsx
import { MsalProvider } from '@azure/msal-react';
import { msalInstance } from '../services/msal';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return (
    <MsalProvider instance={msalInstance}>
      <Component {...pageProps} />
    </MsalProvider>
  );
}

export default MyApp;
```

## Sign-in Functionality
The **MSAL** React library allows us to protect our pages and components by wrapping them with the `MsalAuthenticationTemplate` component. Paired with `UnauthenticatedTemplate`, this can be useful when rendering specific content to authenticated or unauthenticated users respectively. 

Update our home page `pages/index.js`, with the following code

```jsx
import {
  AuthenticatedTemplate,
  UnauthenticatedTemplate,
  useMsal,
} from '@azure/msal-react';
import Head from 'next/head';
import styles from '../styles/Home.module.css';

function SignInButton() {
  // useMsal hook will return the PublicClientApplication instance you provided to MsalProvider
  const { instance } = useMsal();

  return <button onClick={() => instance.loginRedirect()}>Sign In</button>;
}

function WelcomeUser() {
  const { accounts } = useMsal();
  const username = accounts[0].username;

  return <p>Welcome, {username}</p>;
}

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Azure AD Authentication using MSAL and Next.js</title>
      </Head>

      <AuthenticatedTemplate>
        <p>This will only render if a user is signed-in.</p>
        <WelcomeUser />
      </AuthenticatedTemplate>
      <UnauthenticatedTemplate>
        <p>This will only render if a user is not signed-in.</p>
        <SignInButton />
      </UnauthenticatedTemplate>
    </div>
  );
}
```

If you run the application (`npm run dev`), you should see the following in the browser.

![Unauthenticated Render MSAL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uk3pvu8ju3eoogl2lh0n.png)

When you click the sign in button, you will be prompted to sign in and accept requested permissions...

![Login Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/47mffs0514vey36s8nkn.png)

... and then you will be redirected back to the application.

![Authenticated render MSAL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3y5grhayol5tia13r1hx.png)

Notice the change in content rendered, when unauthenticated to authenticated. This is determined by the `UnauthenticatedTemplate` and `AuthenticatedTemplate` wrappers.

MSAL React also provides an alternative way to determine a user's authentication status using hooks, specifically the `useIsAuthenticated` hook. Learn more [here](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-react/docs/hooks.md#useisauthenticated-hook)

## Sign-out functionality
Make the following changes to `pages/index.js`

```jsx
...
// Define sign out button
function SignOutButton() {
  const { instance } = useMsal();

  return <button onClick={() => instance.logoutRedirect()}>Sign Out</button>;
}

...

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Azure AD Authentication using MSAL and Next.js</title>
      </Head>

      <AuthenticatedTemplate>
        <p>This will only render if a user is signed-in.</p>
        <WelcomeUser />
        <SignOutButton /> // <-- Add to authenticated content
      </AuthenticatedTemplate>
...

```

Run the app again, if not already running, `npm run dev`. 
The authenticated render should now look like this...

![Logout Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl1fucztwsjuzxz5x60v.png)

Clicking the sign-out button will redirect and prompt you to select the account to sign out from...

![Logout Azure AD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxyy59iidgc30jie7v0j.png)

You can read more about Sign in and sign out functionality [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-sign-in?tabs=javascript2).

## That's it! What's Next?
We have successfully built a simple Next.js app with MSAL authentication. We can now [acquire access tokens](https://docs.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-acquire-token?tabs=react) which can be used to call APIs securely. Let me know if you would like me to write another guide like this one about how you acquire and use tokens in Next.js. Leave a comment below or [tweet me](https://twitter.com/daryllukas/)

Check out the [full source code](https://github.com/daryllukas/msal-next-auth) on Github.