JavaScript Development Space

Implement Google & GitHub Login in Next.js with NextAuth

30 October 202417 min read
Next.js Auth: Implement Google & GitHub Login with NextAuth

Implementing user authentication is a foundational part of building secure and dynamic web applications. In this article, we’ll walk through how to set up authentication in a Next.js application, using NextAuth for seamless integration with Google and GitHub OAuth providers, and Prisma to manage our user data in a database. By the end of this guide, you’ll have a solid authentication setup with external OAuth providers that store user data efficiently.

We’ll use the newly released Next.js version 15, PostgreSQL set up via Docker, Prisma for type safety, and ShadcnUI for fast UI development. By the end, we'll have an application where users can authenticate via Google or GitHub, with their data instantly stored in our database.

Prerequisites

  1. Basic knowledge of Next.js - Familiarity with Next.js and its folder structure will help.
  2. Node.js and npm installed - You’ll need both installed on your local machine.
  3. A GitHub and Google account - For testing the OAuth flow. Prisma CLI - Make sure you have the Prisma CLI installed, as we’ll use it to set up and migrate the database.
  4. Docker: Install Docker to easily manage your PostgreSQL database in a containerized environment. Refer to the Docker documentation for installation instructions.
  5. PostgreSQL: Familiarity with PostgreSQL is beneficial, as we will use it as our database.
  6. Familiarity with Prisma: Basic knowledge of Prisma ORM for managing database operations will be useful.

Steps to Create User Authentication

Let’s dive into setting up the project and adding user authentication.

Step 1: Initialize Next.js Project

Start by creating a new Next.js project.

npx create-next-app@latest next-oauth-prisma
Loading code editor...

then

cd next-oauth-prisma

Once your project is created, install dependencies:

npm install next-auth@beta @prisma/client prisma
  • next-auth: Handles authentication.
  • @prisma/client and prisma: Used to interact with the database and manage user data.

Now, initialize your Prisma ORM project by generating a Prisma schema file using this command:

npx prisma init --datasource-provider postgresql

Step 2: Setup a Database

Before connecting our database, we first need to create it. To understand Docker better, you can refer to our article, How to Set Up a Local PostgreSQL Using Docker Compose.

Open the Docker application, and if you have other PostgreSQL containers running, stop them to avoid port conflicts. Then, create a docker-compose.yml file and add the following code to it:

Loading code editor...

This Docker Compose file is configured to set up a PostgreSQL database container for your Next.js project with Prisma. Here’s a breakdown:

  • image: postgres:latest pulls the latest PostgreSQL image from Docker Hub.
  • container_name: Names the container next-oauth-prisma, which makes it easy to reference.
  • environment: Sets PostgreSQL environment variables:
  • POSTGRES_USER: the username (set here to postgres_user).
  • POSTGRES_PASSWORD: the password (postgres_password).
  • POSTGRES_DB: the name of the initial database to be created (postgres_auth).
  • ports: Exposes the container’s PostgreSQL port (5432) to the host’s port 5432. This makes the database accessible from outside the container via localhost:5432.

volumes:

  • postgres_data:/var/lib/postgresql/data: Mounts a named volume postgres_data to persist database data on the host, so data is preserved between container restarts.
  • ./init.sql:/docker-entrypoint-initdb.d/init.sql: Mounts an optional SQL script (init.sql), which can initialize the database with predefined tables or values on first run. This script is run automatically by PostgreSQL at startup if present.

Run

docker-compose up -d

Running docker-compose up -d is a way to start the containers defined in your docker-compose.yml file with some specific advantages:

  1. Detached Mode (-d): The -d flag stands for "detached mode," meaning the containers will run in the background. This allows you to keep using your terminal for other commands while your Docker services are running.
  2. Automatic Setup: This command automatically builds and starts up all the services defined in your docker-compose.yml file. In this case, it will set up and start the PostgreSQL database container with the specified configuration.
  3. Persistent Services: Running the container in detached mode is ideal for databases and other services that need to run continuously, as they keep running even if you close the terminal. You can stop them later using docker-compose down.
  4. Networking and Dependencies: If there are multiple services in your docker-compose.yml file that depend on each other, docker-compose up -d will ensure they start in the correct order and are networked together as defined.

In short, using docker-compose up -d is a convenient way to start your database in the background, letting you continue development without an open Docker terminal session.

Step 3: Configure Prisma

Configure Prisma by creating a .env file in the root directory with the following:

Loading code editor...

Replace username, password, and postgres_auth with your actual credentials.

Define the User Model in Prisma

Open prisma/schema.prisma and define the User model for NextAuth. Also, configure Prisma to use PostgreSQL.

Loading code editor...

Each model represents a table in the database, with Prisma creating these tables based on the defined schema. Here’s a breakdown of each model:

User Model

Defines a table for user information with fields for basic attributes like name, email, and role. Key points include:

  • id: A unique identifier with a default value generated by cuid().
  • email: A unique email field.
  • createdAt and updatedAt: Timestamps to track creation and update times, with updatedAt auto-updating on changes.
  • Relationships with other models (Account and Session) are represented as arrays.
  • @@map("users"): Renames the table in the database to users.

Account Model

Stores information about users’ accounts for third-party providers like Google or GitHub:

  • userId: Links to the User model through a foreign key, creating a relationship with the User table.
  • Other fields, like access_token, refresh_token, and expires_at, store authentication data.
  • @@id([provider, providerAccountId]): Composite primary key across provider and providerAccountId fields, enforcing uniqueness for each account.
  • @@map("accounts"): Names the table accounts in the database.

Session Model

Tracks each login session for users:

  • sessionToken: A unique session identifier.
  • expires: Indicates session expiry time.
  • The user field defines a foreign key relationship to the User table, with sessions deleted if the associated user is removed.
  • @@map("sessions"): Names the table sessions in the database.

VerificationToken Model

Used for managing passwordless login or account verification tokens:

  • identifier and token act as composite primary keys, ensuring uniqueness.
  • expires: Expiration timestamp for the token.
  • @@map("verification_tokens"): Names the table verification_tokens.

This schema allows for efficient management of user data, third-party account integrations, user sessions, and account verifications for a complete authentication system.

Run the following commands to create and migrate your database:

npx prisma migrate dev --name init

Step 4: Install ShadcnUI Package

We won't be building the entire project; instead, we'll just create a navbar with a user dropdown menu. To do this, we only need two components from the Shadcn library: Button and Dropdown Menu.

Run the following command to install the required ShadcnUI components package:

npx shadcn-ui init
Loading code editor...

Add ShadcnUI Components

npx shadcn@latest add button

and

npx shadcn@latest add dropdown-menu

Now we’ve added everything needed to our project. In the next section, we’ll start building our UI and connect to the database.

Try running the project with:

npm run dev

Note: The latest version of Next.js has a bug with webpack, causing the error: "Module parse failed: Bad character escape sequence." We've previously covered a solution for this issue — read more about it here.

Create UI

Here's what we aim to build:

OAuth header

To achieve this, we'll need the following components: logo, header, navbar, and user-button.

Logo component

Create logo.tsx file inside the ui folder:

Loading code editor...

User Button Component

Create user-button.tsx inside the components folder

Loading code editor...

Our login component will have three states: loading, sign in, and an avatar with a dropdown menu. To set this up, we need to follow these steps:

login statuses

Here's how to do it:

Loading code editor...
  • useSession hook fetches the current session’s state and data, assigning it to session.
  • The user variable extracts the user object from the session data.

Rendering Logic:

If the user is logged in (user exists):

  • The UserButton component is rendered, displaying user-related options (e.g., an avatar with a dropdown menu).

If the session is loading (user state is undetermined):

  • It displays "Loading user..." to inform users that the status is being fetched.

If no user is logged in (and session isn’t loading):

  • It shows a Sign in button, which triggers the signIn function when clicked.

To add the user variable to the session, we need to adjust our layout.tsx slightly by wrapping it with our session HOC (Higher Order Component).

Layout Component

Loading code editor...

Declare a module augmentation for next-auth:

Create a file src/types/next-auth.d.ts

Loading code editor...

The Session interface is modified to add a user object that combines User and the default structure of user in DefaultSession. This helps TypeScript understand that your session's user now includes the additional properties you defined in the User interface.

A new User interface is defined, adding a role property (type string | null) to store additional user role information. This is useful when you want to store user roles in the session for access control.

By adding these properties, you gain strongly typed access to user.role when working with NextAuth sessions, which makes it easier to implement role-based features or access control in your app.

Declare globalThis.prismaGlobal

Create a file src/lib/prisma.ts

Loading code editor...

In summary, this code helps avoid reinitializing Prisma in development by using a singleton pattern, optimizing both development and production performance.

All that’s left is to create the Header component, where we’ll combine our logo and navbar, and then integrate it into layout.tsx.

Header Component

Loading code editor...

Test it

npm run dev

Set Up NextAuth

Now, we’ll set up NextAuth to authenticate users using Google and GitHub. In the app/api/auth/[...nextauth] directory, create a new folder called auth and a file called route.ts.

Loading code editor...

In the root directory create 2 files: _middleware.ts and auth.ts

auth.ts

Loading code editor...

In this file:

  • We define Google and GitHub as OAuth providers.
  • We configure the PrismaAdapter to manage data in the database.

_middleware.ts

Loading code editor...

Add your Google and GitHub OAuth credentials to the .env file:

Loading code editor...

GitHub OAuth App

Creating a new GitHub OAuth App involves a few steps within the GitHub developer settings. Here’s a quick guide to help you set it up:

1. Go to GitHub Developer Settings:

  • Log in to your GitHub account.
  • Navigate to GitHub Developer Settings by clicking on your profile icon, selecting Settings, and then Developer settings from the sidebar.

2. Create a New OAuth App:

  • In the OAuth Apps section, click on New OAuth App.

3. Fill in the OAuth App Details:

  • Application name: Enter a name for your app, which users will see when authorizing.
  • Homepage URL: Add the main URL for your application, such as https://localhost:3000.
  • Authorization callback URL: Enter the URL where GitHub should redirect users after they authorize, typically something like https://localhost:3000/api/auth/callback/github (depending on how you've set up your app to handle callbacks).

4. Register the Application:

  • Once all fields are filled in, click Register application. GitHub will generate a Client ID and Client Secret for your OAuth app.

5. Secure the Client Secret:

  • Copy the Client ID and Client Secret. Keep these safe, as you’ll need them to configure OAuth in your application, and don’t expose them publicly.

6. Use in Application:

In your application code, use the Client ID and Client Secret to configure GitHub as an authentication provider (for example, using NextAuth or a similar library).

Your GitHub OAuth App is now ready! You can use it to authenticate users through GitHub in your application.

Google OAuth App

To create a new Google OAuth App, follow these steps within the Google Cloud Console:

1. Go to the Google Cloud Console:

2. Create or Select a Project:

  • From the top menu, click Select a project.
  • Choose an existing project or click New Project to create a new one specifically for your app.

3. Enable the OAuth API:

  • In the left sidebar, go to APIs & Services > Library.
  • Search for Google Identity or OAuth and click Enable on the Google Identity API.

4. Configure the OAuth Consent Screen:

  • Go to APIs & Services > OAuth consent screen.
  • Select External if your app will be available to general users, or Internal if it’s restricted to your organization (G Suite users only).
  • Fill out the App name, User support email, and any other required fields.
  • In Scopes for Google APIs, add scopes relevant to your app (e.g., user profile data).
  • Save and continue to configure the consent screen.

5. Create OAuth Credentials:

  • Navigate to APIs & Services > Credentials and click on Create Credentials > OAuth Client ID.
  • For Application type, choose Web application.
  • Under Authorized redirect URIs, add the callback URL for your application. This is typically in the format: https://localhost:3000/api/auth/callback/google

Replace localhost:3000 with your app’s actual domain.

6. Save Your Client ID and Client Secret:

  • After creating the credentials, Google will provide a Client ID and Client Secret.
  • Copy these, as you’ll need them to configure Google authentication in your app.

Your Google OAuth App is now configured and ready for use in your application.

We have one last step: configuring remote image handling in Next.js. To load images from external sources like Google and GitHub in our Next.js app, we need to set trusted image sources in the next.config.ts configuration file. Here’s how:

Loading code editor...

The remotePatterns array lists trusted sources for loading images from external domains. This is useful when users authenticate with Google or GitHub, allowing us to display their profile images securely.

Test and Verify Authentication

After setting up the database, NextAuth configurations, and UI, you can test the authentication workflow. When a user signs in with Google or GitHub, NextAuth will store their information in the database via Prisma, enabling a seamless authentication experience across sessions.

Wrapping Up

With this setup, you’ve established a robust user authentication system in Next.js using NextAuth and Prisma. This implementation is scalable, letting you expand user data management and customize the authentication experience as needed. Using NextAuth with Prisma offers flexibility, and the integration with OAuth providers like Google and GitHub provides a simple, secure way to handle authentication in modern web applications.

Happy coding!

JavaScript Development Space

JSDev Space – Your go-to hub for JavaScript development. Explore expert guides, best practices, and the latest trends in web development, React, Node.js, and more. Stay ahead with cutting-edge tutorials, tools, and insights for modern JS developers. 🚀

Join our growing community of developers! Follow us on social media for updates, coding tips, and exclusive content. Stay connected and level up your JavaScript skills with us! 🔥

© 2025 JavaScript Development Space - Master JS and NodeJS. All rights reserved.