NextAuth.js (v5) - Is there a way to obtain the jwt at every callback call?

2 min read 04-10-2024
NextAuth.js (v5) - Is there a way to obtain the jwt at every callback call?


Unlocking Your JWT with NextAuth.js (v5): A Guide to Consistent Access

Problem:

You're using NextAuth.js v5 for authentication in your Next.js project. You need to access the user's JWT token within your callback functions, but it seems elusive!

Rephrased:

You're using a magical authentication tool (NextAuth.js) to keep your users safe. Now, you want to use the "magic key" (JWT) to perform specific actions after the user logs in, but you can't quite grab it. This article will help you unlock your JWT.

Solution:

While NextAuth.js v5 doesn't directly expose the JWT within every callback function, there are a few clever ways to achieve this:

  1. Leveraging the session object:

    export default async function handler(req, res) {
      const session = await getServerSession(req, res, {
        // Your NextAuth.js configuration here
      });
      
      // Access JWT from the session object
      const jwt = session?.user?.jwt; 
    
      // Proceed with your logic using the JWT
      // ...
    }
    

    NextAuth.js v5 conveniently stores the JWT within the session object. You can access it by navigating through the session object: session.user.jwt. This approach ensures you always have access to the JWT within your callback functions.

  2. Using a Custom Callback:

    export default async function handler(req, res) {
      const session = await getServerSession(req, res, {
        callbacks: {
          jwt: async ({ token, user, account, profile, isNewUser }) => {
            // Modify the token object here (optional)
            if (account?.accessToken) {
              token.accessToken = account.accessToken;
            }
            return token;
          },
          session: async ({ session, token, user }) => {
            // Add the JWT to the session object
            session.jwt = token.accessToken;
            return session;
          }
        },
        // Your NextAuth.js configuration here
      });
    }
    

    This method involves modifying your NextAuth.js configuration to add a custom jwt callback. Within this callback, you can access the token object (containing the JWT). You then add the JWT to the session object within the session callback, ensuring consistent access throughout your application.

Example:

Imagine you're building an API endpoint that requires user authentication. This endpoint should only be accessible if the user has a specific role. You can use the JWT to extract the user's role and grant access:

export default async function handler(req, res) {
  const session = await getServerSession(req, res, {
    // Your NextAuth.js configuration here
  });

  if (!session) {
    return res.status(401).json({ message: 'Unauthorized' });
  }

  const jwt = session.user.jwt; // Access JWT from the session object

  // Decode the JWT and extract the user's role
  const decodedJwt = jwt.decode(jwt.accessToken);
  const role = decodedJwt.role;

  if (role === 'admin') {
    // Allow access
    // ...
  } else {
    return res.status(403).json({ message: 'Forbidden' });
  }
}

Additional Value:

This approach allows you to:

  • Safely store and access JWTs: The session object is securely handled by NextAuth.js, protecting your sensitive JWT from unauthorized access.
  • Improve code organization: Separating JWT handling within specific callbacks promotes cleaner and more maintainable code.
  • Maximize flexibility: You can easily adapt this approach to access the JWT in various scenarios, such as server-side rendering, API calls, or client-side interactions.

References:

Conclusion:

By implementing the techniques outlined above, you can unlock the full potential of NextAuth.js v5 and seamlessly access the JWT within your callback functions. This empowers you to build powerful and secure applications while maintaining a clean and maintainable codebase.