Sunday, January 5, 2025
-
By, Kanad Shee
Next-auth v5 with Prisma, OAuth, Email Verification, Reset Password, 2FA, and more
Integrating authentication into a modern web app can feel intimidating—especially when dealing with complex flows, third-party providers, and secure session handling. But with NextAuth.js v5, the process is not just manageable, it's downright seamless.
In this blog, I walk through how easy it is to set up NextAuth v5 in a real-world application. The new version brings a cleaner API, better TypeScript support, and a more flexible configuration system that aligns perfectly with modern Next.js App Router and Server Actions.
I’ve implemented it in my blog system to allow for a secure and extensible authentication flow without needing to reinvent the wheel. From handling credentials to integrating OAuth providers like GitHub and Google, the new v5 flow felt intuitive, declarative, and scalable. What’s more, the improvements in session handling and server-side logic allowed me to keep the app performant and secure, without overengineering anything.
Whether you're building a personal blog, a SaaS dashboard, or a community platform, NextAuth v5 is a drop-in solution that scales with your project. This post will show you how I made it work—and how you can too—with just a few lines of code and a focus on clean architecture.
Now it will create a prisma folder and will add an .env file in our project directory.
Add DB url in .env
Note: Here make sure to make the password optional as for Google or Github there will be no password.
We can see out created models in our localhost:5555
Now, install prisma client so that we can access all models throughout our project
Note: This is not the right way to do this as it will create a bunch of connection or a connection pool for each time request. So, rather than doing this, we'll do something else.
Next, we have to make two files:
The auth.config.ts is created as in auth we can't use prisma as it it is not edge compatible.
and we will accquire this to auth.ts file
Go to console.cloud.google.com and get the OAuth client id and client secret and add them in .env file
NOTE: Make sure to add Homepage URL and Callback URL in getting the secrets for both the providers.
NOTE: Make sure to change the domain name after deployment
First we will create a custom sign up page.
Let's initialize shadcn for our project.
We'll make a client component RegisterForm as we're going to use hooks states etc.
Inside components dir, create another folder auth and make a component called register-form.tsx
Now, we will create some reusable components which we can use in both signin and register form. For ex: Inside @/components/auth,
These custom compoenent now will be used in register-form or any other component as it needed.
Create a server action.
For that create a new dir as actions in root dir and create a file named register.ts
Now, we can use this server action in our register component.
Our final register component will be:
Here in place of loading we also can use useTransition hook of react also.
This way with google and github we have added credentials configuration also.
Lets build custom buttons for Google and Github login.
For that first make the actions for those buttons
Lets create a component with two buttons Google and Github.
First we have made a custom Goggle-login button.
First of all, as we are using strategy as "jwt", so we are going to use jwt callback
So, now we'll make two utility function which will be called inside this jwt callback
and
NOTE: We do this stuff, as session is accessible in client side but jwt not so we can use user id or image to show their dp or any other stuffs as session is accessible to the client side.
Now, one more callback is there called signIn callback.
Use this signIn() callback to control if a user is allowed to sign in.
So, after adding signIn callback our auth.ts file will be:
For setting up middleware, first we have to make a file named as middleware.ts file.
Now, we will make another file named routes.ts where we can specify our all private, public and auth routes like this:
These two function is going to use in the upcoming sections.
Now, we have to make a function to generate verification token for us.
We have to make a function to send email using Nodemailer package.
We have made this function dynamic for all our upcoming process for verifying email, resetting password and Two factor authentication.
Now before signIn callback run we have to check if the user email is verified or not. If yes then proceed else let the user to verify their email first.
This way we will restrict the user to verify his email before signin.
In same way we can send this email after any user register
Now, we have to make a server action to verify our email.
First lets make two utility function that needed for this.
and
We've use this form inside app > auth > email-confirmation > page.tsx
Note: Now after changing schemas don't forget to run:
In mailSender.ts we have configured email template for 2FA.
Now, we'll modify our login.ts server action and auth.ts file.
Here, we're returning twoFactor: true to the frontEnd so that we can render a form to enter two factor code.
These porition of code is modified in login.ts file and in signIn callback:
Here, we have added some more user details in session in auth.ts file.
So, according to the documentation of Auth.js, we can add one more file next-auth.d.ts file and there we can add those fields types in the user and can export that and can be used throughout the application.
For ex: