Vishesh Duggar bio photo

Vishesh Duggar

5x founder. Co-founder & CTO Product @vamstar. 15+ years building and advising startups of all sizes. If you're building something cool, I'd love to hear about it.

Looking for advice on product, strategy or engineering?

Book Appointment

Subscribe to my mailing list


Vamstar LinkedIn Twitter Github

NextAuth.js is a popular authentication library for Next.js applications. It makes it easy to set up authentication providers and handle user sessions. However, one challenge that developers often face is ensuring that OAuth tokens remain fresh. This article outlines how to handle token refresh with NextAuth.js and Prisma.

Overview

When integrating OAuth providers like Google or Discord, it’s essential to handle token refresh to ensure that the tokens remain valid. This is particularly important for scenarios where your application needs to make authenticated requests to third-party APIs on behalf of the user.

While doing this with Google you might get the following error.

401 Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.

In this guide, we’ll look at how to handle token refresh using the signIn and signOut events provided by NextAuth.js, and how to update the token information in the database using Prisma.

Prerequisites

  • A Next.js application with NextAuth.js and Prisma set up.
  • OAuth set up with a provider like Google or Discord.

Updating Tokens on Sign-In

When a user signs in, we can use the signIn event to update the token information in the database. This is where you add the code snippet for handling the sign-in event.

export const authOptions: NextAuthOptions = {
  callbacks: {
    // ...other callbacks
  },
  events: {
    signIn: async (message) => {
      console.log("signIn", JSON.stringify(message, null, 2));
      const { account, user } = message;
      const { access_token, refresh_token, expires_at } = account!;
      
      await prisma.account.updateMany({
        data: {
          access_token,
          refresh_token,
          expires_at,
        },
        where: {
          AND: [
            {
              userId: user.id,
              provider: "google",
            },
          ],
        },
      });
      console.log(`Added user account with ID: ${user.id}`);
    },
    // ...other events
  },
  // ...other options
};

Clearing Tokens on Sign-Out

Similarly, when a user signs out, we may want to clear the token information from the database. This section will provide the code snippet for handling the sign-out event.

events: {
    // ...other events
    signOut: async (message) => {
      console.log("signOut", JSON.stringify(message, null, 2));
      const { userId } = message.session as unknown as { userId: string };
 
      try {
          await prisma.account.updateMany({
            data: {
              access_token: null,
              refresh_token: null,
              expires_at: null,
            },
            where: {
              AND: [
                {
                  userId: userId,
                  provider: "google",
                },
              ],
            },
            
          });
        
        console.log(`Deleted user account with ID: ${userId}`);
      } catch (error) {
        console.error(`Failed to delete user account with ID: ${userId}`, error);
      }
    },
},

Conclusion

Handling token refresh is crucial for maintaining a smooth user experience and ensuring that your application can continue to interact with third-party services on the user’s behalf. By leveraging the signIn and signOut events provided by NextAuth.js, and using Prisma to interact with your database, you can ensure that your OAuth tokens remain fresh and functional.


15+ Years strategising and delivering growth, engineering, customer value and more. I have served as a CTO to multiple organizations, including Vamstar, AtruHelp, Billaway, SuperSehat, and more.

If you're a founder or CEO eager to move faster and seek tailored strategies for your unique challenges, don't navigate this journey alone. Reach out to me. Together, we can dissect, refine, and optimize your enterprise's trajectory to withstand the tests of time and innovation. Let's make your vision not just a goal, but an impending reality.

I have limited open hours. Book Appointment