Authentication is a key security feature of any application. But it can be complex to implement properly.
This tutorial will show you an easy and secure way to handle authentication in your apps. It involves allowing trusted organizations (such as Google, Facebook, Github, and so on) to authenticate your users while you focus on building important features in your app.
You will learn how to do this using Nextjs and NextAuth step by step.
You should find this article helpful if you're new to NextAuth. But if you already know how to set up authentication with the Nextjs Page router and you're still trying to transition to the Nextjs App router, then this is for you, too.
Here's a video I made that you can use to supplement what you learn here.
Prerequisites
You need to know the basics of Next.js and Prisma to benefit from this tutorial.
You can catch up on the official Nextjs and Prisma documentation.
What is NextAuth?
NextAuth is an open-source authentication solution for Nextjs applications. It is gradually being developed to provide solutions for every framework or library on the web. You can find more details on the Authjs website.
You can think about NextAuth as an intermediary between your application and established authentication systems. So instead of re-inventing the wheel, you can add this solution to yours and keep building your application.
The cool thing about this tool is that you do not have to pay money to use it. Just pay attention. :)
How to Setup the Project
NexthAuth gives you access to many organizations called providers. These organizations provide some credentials for you to use their authentication system.
This tutorial will cover three of them: Google, GitHub, and Email.
So you'll need to access credentials for each of these providers and bootstrap a boilerplate for Nextjs.
How to Get Google Credentials
You can follow the steps below to get your Google Client ID
and Client Secret
.
Log in to Google Console:
Click on the menu icon by the top-left corner. Select API & Services
and then choose Credentials
.
The screen below comes up. Click on Create Project
:
The page that follows is the form below:
Enter the name of your application and click Create
. You will be redirected to the Credentials
page:
Click on the Create Credentials
button and select the OAuth client ID
option:
You have to configure your consent screen to create an OAuth client ID
. Click on the Configure Consent Screen
button to do this:
Set the User Type
to external
and click Create
:
Next, enter a name, support email, and contact email:
Scroll to the bottom of the page and click Save and Continue
.
The Scopes page now appears. Click Save and Continue
. Then click Save and Continue
on the Tests Users
page. You will be directed to the Summary
page. Review your information and click Back To Dashboard
.
Now try to Create an OAuth client ID, and you should come to the following page:
Select the Web application
option because that is what suits this tutorial
Enter a name for the app:
Add a URI to the Authorized JavaScript origins
. Use http://localhost:3000
. This is the landing page of your application. You will add more URIs as you move to production.
Add http://localhost:3000/api/auth/callback/google
as one of the Authorized redirect URIs
. This is where users will be directed to complete their login with Google.
Click Create
, and that will produce the Client ID
and Client Secret
like in the image below:
Copy them or download the JSON file. You will need them soon.
How to Get GitHub Credentials
The directions below will guide you to get your GitHub Client ID
and Client Secret
.
Login to your Github dashboard and click on the profile image at the top-right-hand corner.
Select Settings
in the drop-down menu:
In the page that follows, scroll down and select Developer Settings
:
Click on OAuth Apps
on the next page and choose to Register a New Application
:
Fill out the form that you see on the page that follows:
- Application name -
auth app
- Homepage URL -
http://localhost:3000/
- Authorization callback URL -
http://localhost:3000/api/auth
Click on the Register Application
button. A new page appears with the GITHUB_ID
and GITHUB_SECRET
:
Click on Generate a new client secret
to see the GITHUB_SECRET
.
How to Get Email Credentials
You can use any email vendor that provides SMTP services. This tutorial will use Gmail. You can check out Mailgun, SendGrid, and others.
You will need the following details:
- EMAIL_SERVER_HOST
- EMAIL_SERVER_PORT
- EMAIL_SERVER_USER
- EMAIL_SERVER_PASSWORD
- EMAIL_FROM
The following steps will lead you to your EMAIL_SERVER_PASSWORD
:
Log in to your Gmail account.
Click on your profile image. It will drop down a menu.
Click on the Manage your Google Account
button. You will be redirected to the page below:
Click on Security
on the side menu. The following page will appear.
You will need to set up 2-Step Verification for this process to work. If you have yours done already, click on it.
It will require your password, after which you will be redirected to the following page:
Scroll to the bottom and click on App passwords
, as in the image above.
The page that shows will look like the image below:
Select an App
and a device
from the drop-down and click on the Generate
button:
That will now generate a 16-digit text like this:
Your Email credentials will be as follows:
- EMAIL_SERVER_HOST="smtp.gmail.com"
- EMAIL_SERVER_PORT=465
- EMAIL_SERVER_USER="<your_email_address>". An example is “eberenjoku@gmail.com”
- EMAIL_SERVER_PASSWORD="<the_password_you_just_generated_with_no_spaces>"
- EMAIL_FROM="<the_email_address_you_want_recipient_to_see_as_the_sender>". This email doesn’t have to be in existence.
How to Bootstrap a Next.js Project
You will create 2 Next.js boilerplates. One will use the page router
, while the other will work with the app router
.
Page Router
Run the following command to create a Next.js project:
npx create-next-app@latest
You will get multiple prompts. Your answers should be as follows:
What is your project named? page_router_tutorial
Would you like to use TypeScript with this project? No
Would you like to use ESLint with this project? No
Would you like to use Tailwind CSS with this project? No
Would you like to use `src/` directory with this project? No
Use App Router (recommended)? No
Would you like to customize the default import alias? No
You will now have a project created with a pages
directory like this:
App Router
Run the following command to create a Next.js project:
npx create-next-app@latest
You will get multiple prompts. Your answers should be as follows:
What is your project named? app_router_tutorial
Would you like to use TypeScript with this project? No
Would you like to use ESLint with this project? No
Would you like to use Tailwind CSS with this project? No
Would you like to use `src/` directory with this project? No
Use App Router (recommended)? Yes
Would you like to customize the default import alias? No
You will now have a project created with an app
directory like this:
Everything is now set. You will now begin creating the authentication application.
How to Setup Prisma and NextAuth on the Page and App Router
This section will focus on processes that didn’t change with the release of Next.js 13. So everything you will do in this section will be applied to both the page_router_tutorial
and app_router_tutorial
projects.
You will do the following:
- Install Dependencies
- Create and migrate a database model
- Add the credentials that you got in the previous segment to a file
How to Install Dependencies
The command below will install all the modules for the project:
npm i next-auth prisma nodemailer faunadb @next-auth/prisma-adapter
It adds NextAuth, Prisma, Node Mailer, Fauna DB, and Prisma Adapter modules to the project.
How to Create and Migrate a Database Model
A database model defines how tables in the database communicate with each other. You will create that in this part.
Begin by running the following command:
npx prisma init
It creates a Prisma
directory with a file inside called schema.prisma
and a .env
file in the project’s root folder. The file will contain your model definition.
Currently, the file content looks like this:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
This tutorial will use the Postgres database as indicated in the code above. The .env
file has the DATABASE_URL
that you need to replace with your own. Do not forget to do that to avoid bugs later in the project.
Add the code below to the schema.prisma
file:
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
oauth_token_secret String?
oauth_token String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
This defines four (4) tables: Account
, User
, Session
, and VerificationToken
. The model shows that a user
can have multiple accounts, and each account
may be logged into many places (sessions
). The VerificationToken
table is for verifying a user.
It is now time to create the tables in the database. Run the command below to make it happen:
npx prisma migrate dev
You can then check your database dashboard for the new tables.
You can manage your database from the browser using Prisma by executing the command below:
npx prisma studio
How to Add Credentials to the .env File
The .env file will hold all the details of your providers and other items. These are the credentials:
-
EMAIL_SERVER_USER
-
EMAIL_SERVER_PASSWORD
-
EMAIL_SERVER_HOST
-
EMAIL_SERVER_PORT
-
EMAIL_FROM
-
GITHUB_ID
-
GITHUB_SECRET
-
GOOGLE_CLIENT_ID
-
GOOGLE_CLIENT_SECRET
Aside from these that you already know, you need two more:
- NEXTAUTH_SECRET
- NEXTAUTH_URL
NEXTAUTH_SECRET
can be anything you choose. However, you want something hard to predict. Run the following command to get a very random string:
openssl rand -base64 32
Use the output as the NEXTAUTH_SECRET
.
NEXTAUTH_URL
is the base URL of your project. Since the project is still in development, the NEXTAUTH_URL
is http://localhost:3000
.
Here is what your .env
file should look like this:
DATABASE_URL="postgres://postgres:IcuI4cu.31904145.@db.tbwiajqcroukpykndvft.supabase.co:5432/postgres"
EMAIL_SERVER_HOST="smtp.gmail.com"
EMAIL_SERVER_PORT=465
EMAIL_SERVER_USER="tsendgrid7@gmail.com"
EMAIL_SERVER_PASSWORD="cnbpfzfrjnxvfgcv"
EMAIL_FROM="no-reply@tsendgrid7.com"
GOOGLE_CLIENT_ID="196506336558-lh9qhavsi224v00n7q6ggn1f6cur9epr.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="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"
GITHUB_ID="11a8144f2897384cfedf"
GITHUB_SECRET="6599042d48110bbda9fcd1ec6ede61f4320adc9d"
NEXTAUTH_SECRET="YegyDIZNJPqxOkGS4K0F/o9l3SjCxCUR4Q/45rGyOtA="
NEXTAUTH_URL="http://localhost:3000"
That concludes what is the same process for both projects. The following section will now focus on the page_router_tutorial
directory.
How to Create Authentication with the Next.js Page Router
Now I'll go through what you need to do in the page_router_tutorial
folder. Follow the steps below:
Make a folder called auth
in the pages/api/
directory. Create a file in the pages/api/auth
directory and name it [...nextauth].js
.
Import PrismaAdapter
, PrismaClient
, and NextAuth
:
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import { PrismaClient } from '@prisma/client';
import NextAuth from "next-auth";
Also, import the providers like this:
import EmailProvider from "next-auth/providers/email";
import GitHubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
Instantiate the PrismaClient
and export NextAuth as default. Use the code below:
const prisma = new PrismaClient();
export default NextAuth();
This code will automatically create and handle the API routes for authentication.
Next, export a NextAuth
function and add the adapter to it like this:
export default NextAuth({
providers: [...],
adapter: PrismaAdapter(prisma),
});
The providers
key is an array of functions, where each one is the provider that you want to add to your project. You are to add three of them, so your code should look like this:
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export default NextAuth({
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
EmailProvider({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD,
},
},
from: process.env.EMAIL_FROM,
}),
],
adapter: PrismaAdapter(prisma),
});
That is all you need to create an authentication application using Next.js and NextAuth.
Start the local server by running the following command:
npm run dev
Navigate to http://localhost:3000/api/auth/signin, and you will be on this page:
Voilà...Surprise! Surprise! Surprise!
You didn’t create any UI, so where did this UI come from?
Now that is the beauty of NextAuth. It creates endpoints and an accompanying UI for each provider. You don’t have to sweat it, but you can use your UI.
How to Test the Page Router Authentication
The following videos demonstrate how the authentication app you built works:
NextAuth also provides a signout functionality. Navigate to http://localhost:3000/api/auth/signout.
Click on the Signout
button that shows when the page is done loading:
In this section, you learned how to build a Next.js authentication application using the pages
routing pattern. You can find the code for this segment on GitHub: https://github.com/EBEREGIT/nextjs-nextauth-tut/tree/main/page_router_tutorial.
But Next.js version 13 was released a while ago and has gotten stable. It comes with the app routing pattern, and Next.js developers are advised to embrace it since the pages
router may become deprecated soon.
You'll see how to set up Next.js authentication using the app
routing pattern in the next segment.
How to Implement Authentication with the Next.js App Router
This section will show a slightly different and maybe effortless way to implement authentication with the app
router.
You will now turn your attention to the app_router_tutorial
folder.
Do not forget to set up Prisma and NextAuth as you did in the previous section for the page_router_tutorial
project.
Now, do the following:
Create an api
folder in the app
directory.
Make a folder called auth
in the app/api/
directory.
Make a folder called [...nextauth]
in the app/api/auth
directory
Create a file in the [...nextauth]
folder called route.js
. This is in line with Nextjs 13 Route Handlers directive.
In the file, import PrismaAdapter
, PrismaClient
, NextAuth
, and the providers like this:
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import { PrismaClient } from '@prisma/client';
import NextAuth from "next-auth";
import EmailProvider from "next-auth/providers/email";
import GitHubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
Instantiate the PrismaClient
:
const prisma = new PrismaClient();
Create a handler
function to run the NextAuth
configurations with the code below:
const handler = NextAuth(...);
Pass the providers and adapter as one argument into the NextAuth
method. Type the following code:
const handler = NextAuth({
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
EmailProvider({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD,
},
},
from: process.env.EMAIL_FROM,
}),
],
adapter: PrismaAdapter(prisma),
});
Finally, export the handler with the following line of code:
export { handler as GET, handler as POST };
That is all you need for the authentication to work with the app
router.
You will have the same interface as in the previous section if you navigate to http://localhost:3000/api/auth/signin.
The code for this section is on GitHub: https://github.com/EBEREGIT/nextjs-nextauth-tut/tree/main/app_router_tutorial.
How to Test the App Router Authentication
Testing the app
router authentication follows the same procedure as in the page
router.
Conclusion
Implementing authentication can be difficult. But with these helpful tools, it can only get better. This tutorial aimed to teach how to implement authentication using NextAuth both in the Next.js pages
and app
router.
You saw how to set up Prisma and NextAuth in any Next.js project. You also learned the difference between Next.js pages
and app
routing patterns and how to implement the NextAuth authentication logic.
This tutorial just scratched the surface, but it gives you an angle to start building personal projects. Please check out the documentation below to keep learning.
All the code for this tutorial is one GitHub: https://github.com/EBEREGIT/nextjs-nextauth-tut. Please leave a star 😊.