<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sruthi Viswanathan</title>
    <description>The latest articles on DEV Community by Sruthi Viswanathan (@sruthi_13).</description>
    <link>https://dev.to/sruthi_13</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1342195%2F1cc705cd-3e36-42e3-83da-cf6d3e491136.jpeg</url>
      <title>DEV Community: Sruthi Viswanathan</title>
      <link>https://dev.to/sruthi_13</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sruthi_13"/>
    <language>en</language>
    <item>
      <title>Integrating Azure AD as an Identity provider in Next.js with NextAuth</title>
      <dc:creator>Sruthi Viswanathan</dc:creator>
      <pubDate>Sun, 10 Mar 2024 10:32:18 +0000</pubDate>
      <link>https://dev.to/sruthi_13/integrating-azure-ad-as-an-identity-provider-in-nextjs-with-nextauth-4e5b</link>
      <guid>https://dev.to/sruthi_13/integrating-azure-ad-as-an-identity-provider-in-nextjs-with-nextauth-4e5b</guid>
      <description>&lt;p&gt;In this guide, I'll walk you through the process of smoothly setting up AzureAD as the identity provider for your Next.js application using the app router.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This guide assumes that you have already registered your application in Microsoft Azure and have access to the following credentials:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Application (Client) ID&lt;/li&gt;
&lt;li&gt;Directory (Tenant) ID&lt;/li&gt;
&lt;li&gt;Client Secret&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the purpose of this tutorial, let's assume the registered application is named DEMO-APP.&lt;/p&gt;

&lt;p&gt;Now, let's quickly go through a checklist to ensure that we have all the necessary configurations in place for integrating Azure AD with our Next.js app.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;&lt;em&gt;App Registration&lt;/em&gt;&lt;/strong&gt; -&amp;gt; &lt;strong&gt;&lt;em&gt;DEMO-APP&lt;/em&gt;&lt;/strong&gt; and choose the Authentication tab from the left-hand pane.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Configure Redirect URI
&lt;/h3&gt;

&lt;p&gt;Configure the redirect URLs for our application under the Web (Redirect URIs) section. These URLs will serve as destinations for authentication responses (tokens) after successfully authenticating or signing out users.&lt;/p&gt;

&lt;p&gt;The format of the redirect URL is as follows: &lt;code&gt;APP_BASE_URL/api/auth/callback/azure-ad&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local development redirect URL - &lt;a href="http://localhost:4000/api/auth/callback/azure-ad" rel="noopener noreferrer"&gt;http://localhost:4000/api/auth/callback/azure-ad&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Production environment redirect URL - &lt;a href="https://your-custom-domain.com/api/auth/callback/azure-ad" rel="noopener noreferrer"&gt;https://your-custom-domain.com/api/auth/callback/azure-ad&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Enable Implicit grant and hybrid flows
&lt;/h3&gt;

&lt;p&gt;Choose both access tokens and ID tokens under the Implicit grant and hybrid flows section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfcsnvoyp5yqbdumthga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfcsnvoyp5yqbdumthga.png" alt="enable-implicit-grant-hybrid-flows"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Set up the permissions for accessing your application
&lt;/h3&gt;

&lt;p&gt;To restrict access to your application or APIs within your organization, choose "&lt;strong&gt;Accounts in this organizational directory only – (Single Tenant)&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;Then, click on &lt;strong&gt;Save&lt;/strong&gt; to apply the configured authentication settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Azure AD with Next.js Application
&lt;/h2&gt;

&lt;p&gt;Proceed with the following steps to integrate your Next.js application with Azure AD:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Update the necessary credentials in the environment (env) file.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AZURE_AD_CLIENT_ID&lt;/strong&gt; - &lt;em&gt;Application (Client) ID&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;AZURE_AD_CLIENT_SECRET&lt;/strong&gt; - &lt;em&gt;Client Secret&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;AZURE_AD_TENANT_ID&lt;/strong&gt; - &lt;em&gt;Directory (Tenant) ID&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;NEXTAUTH_SECRET&lt;/strong&gt; - &lt;em&gt;Generate a random secret for NextAuth&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;NEXTAUTH_URL&lt;/strong&gt; - &lt;em&gt;Next.js application base URL&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;NEXTAUTH_URL_INTERNAL&lt;/strong&gt; - &lt;em&gt;Next.js application base URL&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

AZURE_AD_CLIENT_ID="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AZURE_AD_CLIENT_SECRET="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AZURE_AD_TENANT_ID="XXXX-XXXX-XXXX-XXXX-XXXX"
NEXTAUTH_SECRET="XXXXXXXXXXXXXXXXX"
NEXTAUTH_URL="http://localhost:4000"
NEXTAUTH_URL_INTERNAL="http://127.0.0.1:4000"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;Note:&lt;/u&gt;&lt;/strong&gt; It is crucial to implement appropriate security measures when adding secrets to the env.production file. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Configuring Authentication for a Next.js Application Using Azure AD as the Authentication Provider and NextAuth
&lt;/h3&gt;

&lt;p&gt;Create a file named &lt;strong&gt;&lt;em&gt;route.ts&lt;/em&gt;&lt;/strong&gt; within the &lt;strong&gt;&lt;em&gt;app/api/auth/[...nextauth]&lt;/em&gt;&lt;/strong&gt; folder, and then paste the following code into it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import NextAuth, { NextAuthOptions } from "next-auth";
import AzureADProvider from "next-auth/providers/azure-ad";
import { cookies } from 'next/headers'

declare module "next-auth" {
  interface Session {
    accessToken?: string;
    idToken?: string;
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    provider?: string;
    accessToken?: string;
    idToken?: string;
  }
}

const authOptions: NextAuthOptions = {
  providers: [
    AzureADProvider({
      clientId: process.env.AZURE_AD_CLIENT_ID as string,
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET as string,
      tenantId: process.env.AZURE_AD_TENANT_ID as string,
      authorization: { params: { scope: "openid profile user.Read email" } },
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET as string,
  callbacks: {
    async jwt({ token, account}) {
      if (account) {
        token.idToken = account.id_token as string;
        token.accessToken = account.access_token as string;
      }
      return token;
    },
    async session({ session, token }) {
      session.accessToken = token.accessToken as string;
      session.idToken = token.idToken as string;
      cookies().set('idToken', session.idToken);
      return session;
    },
  },
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's break down the steps we're taking here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Firstly, we import the necessary modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NextAuth&lt;/code&gt; and &lt;code&gt;NextAuthOptions&lt;/code&gt; from the &lt;code&gt;"next-auth"&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AzureADProvider&lt;/code&gt; from the &lt;code&gt;"next-auth/providers/azure-ad"&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cookies&lt;/code&gt; method from the &lt;code&gt;"next/headers"&lt;/code&gt; library.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we declare interfaces for &lt;code&gt;Session&lt;/code&gt; and &lt;code&gt;JWT&lt;/code&gt; to extend their properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then, we proceed to configure the authentication options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We integrate the &lt;code&gt;Azure AD provider&lt;/code&gt; with essential parameters like clientId, clientSecret, tenantId, and authorization scope.&lt;/li&gt;
&lt;li&gt;Callbacks are set for JWT and session handling:

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;jwt&lt;/em&gt; callback extracts the idToken and accessToken from the Azure AD account object and incorporates them into the JWT token.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;session&lt;/em&gt; callback adds accessToken and idToken to the session object and sets a cookie named 'idToken' with the idToken value.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we initialize NextAuth with the configured &lt;code&gt;authOptions&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we export the NextAuth handler for GET and POST requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Initiate Sign In
&lt;/h3&gt;

&lt;p&gt;Include the following lines of code in your client component, where you want to link the signIn action:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { signIn } from "next-auth/react";


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;button onClick={() =&amp;gt; { signIn('azure-ad') }}&amp;gt;
Sign In
&amp;lt;/button&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Calling &lt;code&gt;signIn()&lt;/code&gt; without any arguments will redirect to the prebuilt sign-in page provided by NextAuth, featuring a button for signing in via Azure AD. Alternatively, directly &lt;strong&gt;&lt;em&gt;invoke the signIn function with the provider's name&lt;/em&gt;&lt;/strong&gt; (in this case, "azure-ad" - &lt;code&gt;signIn('azure-ad')&lt;/code&gt;) from the JSX code to bypass the default sign-in page.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Initiate Sign Out
&lt;/h3&gt;

&lt;p&gt;Include the following lines of code in your client component, where you want to link the signOut action:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { signOut } from 'next-auth/react';


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

async function handleLogout() {
  await signOut({ redirect: false, callbackUrl: "/" });
  push('/');
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;button onClick={() =&amp;gt; {handleLogout}}&amp;gt;
Sign Out
&amp;lt;/button&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Middleware
&lt;/h2&gt;

&lt;p&gt;Having integrated Azure AD as the identity provider with our application, the subsequent task involves safeguarding our endpoints from unauthorized access. Here's what you need to do:&lt;/p&gt;

&lt;p&gt;Generate a file named &lt;strong&gt;&lt;em&gt;middleware.ts&lt;/em&gt;&lt;/strong&gt; within the &lt;strong&gt;&lt;em&gt;root directory&lt;/em&gt;&lt;/strong&gt; of your application.&lt;/p&gt;

&lt;p&gt;Embed the provided code snippet into the middleware file.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

// API Paths to be restricted.
const protectedRoutes = ["/hub"]; 

export default async function middleware(request: NextRequest) {
  const res = NextResponse.next();
  const pathname = request.nextUrl.pathname;
  if (protectedRoutes.some((path) =&amp;gt; pathname.startsWith(path))) {
    const token = await getToken({
      req: request
    });
    // check not logged in.
    if (!token) {
      const url = new URL("/", request.url);
      return NextResponse.redirect(url);
    }
 }
 return res;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here's a breakdown of the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First we import necessary functions and types from the &lt;code&gt;next-auth/jwt&lt;/code&gt; and &lt;code&gt;next/server&lt;/code&gt; modules. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getToken&lt;/code&gt; is imported from &lt;code&gt;next-auth/jwt&lt;/code&gt; to retrieve the user's authentication token. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NextResponse&lt;/code&gt; and &lt;code&gt;NextRequest&lt;/code&gt; are imported from &lt;code&gt;next/server&lt;/code&gt; to handle HTTP responses and requests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An array named protectedRoutes is declared, containing the paths of the routes that require protection. In this example, any route that starts with &lt;code&gt;/hub&lt;/code&gt; route is protected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The middleware function is exported as the default export. It takes a NextRequest object as a parameter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside the middleware function, a NextResponse object res is initialized using NextResponse.next().&lt;/li&gt;
&lt;li&gt;The pathname of the incoming request is extracted from the nextUrl property of the request object.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the requested path matches any of the paths in the protectedRoutes array, the middleware attempts to retrieve the user's authentication token using the &lt;code&gt;getToken&lt;/code&gt; function from &lt;code&gt;next-auth/jwt&lt;/code&gt;. This token represents the user's authentication state.&lt;br&gt;
If no token is found (indicating that the user is not logged in), the middleware redirects the user to the root path of the application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the middleware returns the NextResponse object res. If the requested path does not match any protected routes, the middleware allows the request to proceed without any additional action.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And there you have it! &lt;/p&gt;

&lt;p&gt;In this article, we've successfully integrated our Next.js application with Azure AD as the authentication provider. As a bonus, we've also gained insight into securing our application APIs against unauthorized access by implementing a middleware.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>nextauth</category>
      <category>azuread</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
