Its currently most popular auth solution for nextjs and also integrates well with the nextjs.
Also it allows the entire auth flow to function from within the app and our own database, compared to solutions like clerk.dev and Auth0 which use a third party hosted solution and our user data is not in our own database.
next-auth is rebranding to be more framework agnostic and rebranding to authjs,
However authjs is the v5 version of the library. The v4 version is still known as
next-auth in the docs. For simplicity I will just use the term next-auth but we are
using the latest v5 version in this tutorial. (Sorry, I know its confusing)
First we can setup our next-auth. We use a Google Oauth and email provider setup for authentication.
We first initialize a Prisma client, then pass it in to the authjs prisma adapter.
Then we need to initialize our Google client with the right crediantials. How to create google credentials can be found below. Create Google Oauth Credentials
Next we need to setup up our Email Provider. There are a couple ways to do this. We will simply pass in custom sendVerificationRequest that we will go over in the next section.
We use Session auth for authentication. Session auth requires us to make a request to the db to check auth status vs JWT which just checks for a valid token.
Session is better in SAAS apps because it allows us to maintain a single source of truth in a multi tenancy app.
For example if a user is deleted by an admin, they would still be able to log in if they were using a JWT.
Signout everywhere also only works with session auth.
In some apps jwt can be more efficient since we dont need to make a database call when checking session.
Checkout this comparison of jwt vs session for more info: Jwt vs Session
Installation
To use v5 we need to install the beta version.
npm install next-auth@beta
We can also set our env variables.
NEXTAUTH_URL= is only used in prod. We can comment it out in development mode.
NEXTAUTH_SECRET= is user defined
1NEXTAUTH_URL=
2NEXTAUTH_SECRET=
Below we have our main auth config object.
auth/authConfig.ts
1import NextAuth from 'next-auth';
2import { PrismaAdapter } from '@auth/prisma-adapter';
3import { PrismaClient } from '@prisma/client';
4import Google from 'next-auth/providers/google';
5import EmailProvider from 'next-auth/providers/email';
6import { sendVerificationRequest } from './sendEmail';
7
8const prisma = new PrismaClient();
9
10export const {
11 handlers: { GET, POST },
12 auth
13} = NextAuth({
14 providers: [
15 Google({
16 clientId: process.env.GOOGLE_CLIENT_ID,
17 clientSecret: process.env.GOOGLE_CLIENT_SECRET
18 }),
19 EmailProvider({
20 sendVerificationRequest
21 })
22 ],
23 adapter: PrismaAdapter(prisma),
24 session: { strategy: 'database' },
25 pages: {
26 signIn: '/auth/signin'
27 },
28 callbacks: {
29 async session({ session, user }) {
30 if (user || session) {
31 session.user.id = user.id;
32 }
33 }
34 }
35});
36
Login and Sessions
After setting up the next-auth config object, we can define our login functions.
We will use both Google Oauth and Email provider for our authentication.
We can use the built in signIn() function from next-auth for this.
auth/login.ts
1import 'client-only';
2import { signIn, signOut } from 'next-auth/react';
3import { EmailFormValues } from '@/lib/types/validations';
Next-auth requires using emails for the email auth provider. We need to setup a way to work with emails locally and not send actual emails in development and we also need a transactional email server that can send real emails in production.
We will use 2 different tools for this. We will work with emails locally with Maildev and we can use Resend for sending real emails in prod.
Here we can get our session and User data from the exported auth object in the auth config file.
We can use it to protect auth routes and display user data.
page.tsx
1import { auth } from './auth';
2
3export default async function Page() {
4 const session = await auth();
5 if (!session) redirect('/login');
6
7 return (
8 <div>
9 User Email: {session.user.email}
10 </div>
11 );
12}
13
Testing with playwright
For testing we can setup auth in a setup function and save the auth session in a file. This will allow us to reuse the auth data without having to login in before every test.
We can also call the mail dev api directly to get the redirect URL for email auth.