Setting Up NextAuth, GitHub, and Prisma: A Step-by-Step Guide
Paul Berthelot / April 04, 2023
6 min read • –––
Hey there! Today, I want to share my experience with NextAuth.js. As you know, authentication can be quite challenging, but NextAuth.js is the game-changer we've all been waiting for! This incredible library streamlines authentication in Next.js applications, allowing you to seamlessly work with various providers like GitHub, Google, and many more.
Let's dive into how NextAuth.js operates. First, you'll need to create a [...nextauth].ts
file in your project's pages/api/auth
folder. This file serves as an API endpoint, and NextAuth.js manages all aspects of authentication, from signing in and signing out to handling OAuth flows.
One aspect of NextAuth.js that I truly appreciate is the choice between JSON Web Tokens (JWT) and session-based authentication. With JWT, authentication data is stored in a secure token that's exchanged between the client and the server. Session-based authentication stores the authentication data on the server, with the client holding a session ID.
For most applications, I recommend to choose session-based token. With session-based authentication, the server can store more user information, and managing user sessions becomes a breeze. Additionally, I can invalidate a user's session server-side if needed, which greatly enhances security.
Now let's setting up NextAuth, GitHub, and Prisma in your Next.js application. So, let's dive right in.
Before we begin, make sure you have Next.js, Prisma, and NextAuth installed in your project. If you haven't done that yet, go ahead and follow the official installation guides for each of them.
Alright, now that we're all set, let's take a look at the [...nextauth].ts
file in your project's pages/api/auth
folder:
import NextAuth from "next-auth";
import GithubProvider from "next-auth/providers/github";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { prisma } from "#/lib/prismaclient";
export const authOptions = {
callbacks: {
// 'user' represents the user object stored in our database.
// By customizing the session object, we can selectively pass
// the desired user information to the client and throughout
// our API.
async session({ session, token, user }: any) {
session.user.id = user.id;
return session;
},
},
adapter: PrismaAdapter(prisma),
secret: process.env.SECRET,
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
],
};
export default NextAuth(authOptions);
We start by importing the required packages: NextAuth, GithubProvider, PrismaAdapter, and our Prisma client. Then, we define the authOptions
object, which will be used to configure our NextAuth instance.
callbacks
: We define a custom session callback to include the user's ID in the session object (the informations you want to put in the session will depend on your application use case).adapter
: We use the PrismaAdapter and pass in our Prisma client to integrate with the Prisma ORM.secret
: We set the application secret using an environment variable. To generate a secret just runopenssl rand -base64 32
in your terminal.providers
: We define the GitHub provider by passing in the GitHub app's client ID and secret.
Finally, we export our NextAuth instance with the configured authOptions.
Now, let's take a look at the #/lib/prismaclient.ts
file:
import { PrismaClient } from "@prisma/client";
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
In this file, we import the PrismaClient
from the @prisma/client
package. We then create a global object to store the Prisma client instance, which helps prevent multiple instances of the Prisma client in development.
We export the prisma object, which is either the existing instance or a new one. Finally, we set the global prisma object to the instance we just created if we're in a non-production environment. This code was taken from the official documentation of Prisma.
The PrismaAdapter
we use in the [...nextauth].ts
file needs the following schemas. Note that you can add more user attributes depending of your application use case.
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
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?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@index(userId)
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index(userId)
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
Now let's see how to create a GitHub Application ID and secret
for NextAuth.js authentication. These credentials will enable users to log in to your application using their GitHub accounts. Let's get started!
-
First, head over to the GitHub Developer settings page by visiting https://github.com/settings/developers. Here, you'll find an overview of your existing OAuth apps (if you have any). To create a new one, click on the "New OAuth App" button.
-
Fill out the "Application name," "Homepage URL," and "Application description" fields with the relevant information for your app. The "Homepage URL" should be the URL of your app's landing page (e.g., https://your-app-domain.com).
-
Next, enter the "Authorization callback URL." This is where GitHub will redirect the user after they've successfully authorized your app. For NextAuth.js, the callback URL should be in the format: https://your-app-domain.com/api/auth/callback/github.
-
Click the "Register application" button to create your new OAuth app. After registration, you'll be redirected to your app's settings page.
-
On the app settings page, you'll find your newly generated "Client ID" and "Client Secret." Make sure to keep these credentials safe, as they're essential for authenticating users with GitHub through NextAuth.js.
Now that you have your GitHub Application ID and secret, you can plug them into your NextAuth.js configuration. In your [...nextauth].ts
file, update the providers
array with the GithubProvider
and include your clientId
and clientSecret
:
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
],
To work with local and production environment, you will need to create two OAuth apps. For the local development, use this url format: http://localhost:3000/api/auth/callback/github.
And that's it! You now have a working setup for NextAuth, GitHub, and Prisma in your Next.js application. With this setup, you can easily manage user authentication using GitHub and handle your application's data with Prisma.
Subscribe to the newsletter
Get emails from me about web development, tech trends, and advices for founders.
24 subscribers