Securely Handling Azure AD Access Tokens with NextAuth.js in a Next.js Application – Azure

by
Ali Hasan
access-token aws-security-group azure-active-directory django-authentication reactjs

Quick Fix: To securely handle Azure AD access tokens in Next.js using NextAuth.js, remove the access token from the session and use an adapter to store custom session data in a database. Instead of returning the access token in the session callback, return only non-sensitive data. Create an API route to query Microsoft Graph using the access token and call it from your Next.js component using SWR. Consider securing environment variables containing sensitive information for improved security.

The Problem:

How to securely handle Azure AD access tokens in a Next.js application using NextAuth.js. The access token is currently visible in the React context, which is a security risk. Are there better ways to store and manage the access token securely on the client side?

The Solutions:

Solution 1: Removing Access Token from Session and Using API Route to Access Microsoft Graph API

To address the security concern of having the access token visible in the React context, you can remove it from the session and rely on a server-side API route to handle authenticated requests to the Microsoft Graph API.

Steps:

  1. Remove access token from session: Update your NextAuth configuration to remove the access token from the session:

    async session({ session, token, user }) {
      // Don't include the access token in the session.
      return session;
    }
    
  2. Create API route: Create a new API route to handle requests to the Microsoft Graph API. In this route, retrieve the access token from the request using next-auth/jwt. Format the fetch request to include the access token in the Authorization header.

    import { NextResponse } from 'next/server';
    import { redirect } from 'next/navigation';
    import { getToken } from 'next-auth/jwt';
    
    export async function GET(req: Request) {
      const token = await getToken({ req });
    
      // If the user isn't signed in, redirect.
      if (!token) return redirect('/signin');
    
      // Modify the fetch request to match your needs.
      const res = await fetch(`https://graph.microsoft.com/{version}/{resource}?{query-parameters}`, {
        headers: { Authorization: `Bearer ${token?.accessToken}` },
      });
    
      const data = await res.json();
    
      return NextResponse.json({ data });
    }
    
  3. Consume API route: In your components, call the API route to make authenticated requests to the Microsoft Graph API. Use a library like swr to handle caching and error handling.

    import useSWR from 'swr';
    
    export default function Component() {
      const { data, error, isLoading } = useSWR('/api/msgraph', fetcher);
    
      if (error) return <div>❌</div>;
      if (isLoading) return <div>&#128565;️&#128171;</div>;
    
      console.log('ms graph response', data);
      return <div>{data.someProp}</div>;
    }
    

By following these steps, you can securely handle access tokens on the client-side without compromising their confidentiality.

Q&A

Should I be concerned about the visibility of the access token in the React context?

Yes, it poses a security risk.

What alternative strategies can I use to store and manage the access token securely?

Use session storage, local storage, or cookies.

What is a more secure way to handle the access token on the client side in a Next.js application using NextAuth.js?

Consider using an API route to query Microsoft Graph and handle authenticated requests on the server side.

Video Explanation:

The following video, titled "How to Manage Backend JWT Access Tokens in Next Auth and Next ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

... Next-auth and Next.js 13. We'll cover how to store and access backend JWT tokens inside the Next-Auth session in Next.js applications. #nextjs13 ...