Skip to main content

Command Palette

Search for a command to run...

Implementing Google Login in NextJS 14: A Complete Guide with AuthJS 5, MongoDB, and Prisma ORM

Unlock the power of seamless Google authentication in your Next.js 14 applications using the latest NextAuth.js 5 (beta), Prisma ORM, and MongoDB.

Updated
•7 min read
Implementing Google Login in NextJS 14: A Complete Guide with AuthJS 5, MongoDB, and Prisma ORM
S

đź‘‹ Hey there! I'm a passionate developer with a knack for creating robust and user-friendly applications. My expertise spans across various technologies, including TypeScript, JavaScript, SolidJS, React, NextJS.

Introduction

In today’s digital landscape, secure user authentication is crucial for any web application. Google authentication provides a seamless and secure way for users to log in using their Google accounts. This tutorial will guide you through implementing Google authentication in a NextJS 14 application using AuthJS 5, MongoDB, and Prisma ORM.

By the end of this article, you’ll have a robust authentication system that leverages the power of modern web technologies, ensuring both security and ease of use.

Let’s dive in and get started with setting up our NextJS project!


Setting Up the Project

1. Initialize a NextJS Project

First, we’ll create a new NextJS project named nextjs-google-auth by running the following command:

npx create-next-app@latest nextjs-google-auth

Follow the prompts to set up the project according to your preferences.

2. Navigate to the Project Directory

Move into the newly created project directory:

cd nextjs-google-auth

3. Install Necessary Dependencies
Next, install the required packages for authentication and database management:

npm install next-auth@beta @prisma/client @auth/prisma-adapter
npm install prisma --save-dev

Note: We use next-auth@beta because Auth.js version 5 is currently in beta. If you're reading this in the future when Auth.js 5 is fully released, you can install it with npm install next-auth .

4. Set Up Google Auth Credentials
We will need a Google Auth Client ID and Client Secret. To generate these credentials:

  • Go to the Google Cloud Console

  • Register a new application and create OAuth 2.0 credentials.

  • Set the Callback URL to: https://<your-site>/api/auth/callback/google .

Copy the generated Client ID and Client Secret, and paste them into the .env file in your project directory:

AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_SECRET="your-google-client-secret"

5. Generate an Auth Secret
Run the following command to generate a secret for authentication and add it to the .env file:

npx auth secret

Add the generated secret to your .env file:

AUTH_SECRET="your-auth-secret"

6. Set Up the Database

Go to the MongoDB website and create a new database. Once the database is created, obtain the connection string.

Remember to include your database name in the connection string. Add this connection string to your .env file:

DATABASE_URL="mongodb+srv://<username>:<password>@<cluster-url>/<your-db-name>?retryWrites=true&w=majority&appName=<app-name>"

This sets up the basic configuration for your project, ensuring you have the necessary environment variables and dependencies to proceed with implementing Google authentication.

Next, we will configure Prisma to work with MongoDB.


Configuring Prisma ORM

1. Initialize Prisma
Run the following command to initialize Prisma with MongoDB as the datasource provider:

npx prisma init --datasource-provider mongodb

This will generate a prisma folder and a schema.prisma file inside it.

2. Configure the Prisma Schema
Replace the contents of the prisma/schema.prisma file with the following:

// prisma/schema.prisma

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id            String    @id @default(auto()) @map("_id") @db.ObjectId
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
}

model Account {
  id                String   @id @default(auto()) @map("_id") @db.ObjectId
  userId            String   @db.ObjectId
  type              String
  provider          String
  providerAccountId String
  refresh_token     String?  @db.String
  access_token      String?  @db.String
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String?  @db.String
  session_state     String?
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
  user              User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

3. Generate Prisma Client
Run the following command to generate the Prisma client based on the updated schema:

npx prisma generate

This configures Prisma to work with MongoDB and sets up the necessary models for handling user authentication data.


Configuring the Database Connection and Authentication

1. Create alibFolder
Inside the src folder, create a lib folder to store our database and authentication configurations.

2. Createdb.tsin thelibFolder
Create a db.ts file inside the lib folder with the following content:

// @/lib/db.ts

import { PrismaClient } from "@prisma/client";

const prismaClientSingleton = () => {
  return new PrismaClient();
};

declare global {
  var prisma: undefined | ReturnType<typeof prismaClientSingleton>;
}

const db = globalThis.prisma ?? prismaClientSingleton();

export default db;

if (process.env.NODE_ENV !== "production") globalThis.prisma = db;

3. Createauth.config.tsin thelibFolder
Create a auth.config.tsfile inside the lib folder with the following content:

// @/lib/auth.config.ts

import { NextAuthConfig } from "next-auth";
import Google from "next-auth/providers/google";

export const authConfig: NextAuthConfig = {
  providers: [Google],
};

4. Createauth.tsin thesrcFolder
Create a auth.ts file inside the src folder with the following content:

// @/auth.ts

import NextAuth from "next-auth";
import { authConfig } from "@/lib/auth.config";
import { PrismaAdapter } from "@auth/prisma-adapter";
import db from "@/lib/db";

export const { handlers, signIn, signOut, auth } = NextAuth({
 ...authConfig,
 adapter: PrismaAdapter(db),
 session: {
  strategy: "jwt",
 },
 pages: {
  signIn: "/login",
 },
 callbacks: {
  async jwt({ token, user }) {
   if (user) {
    // get user from db with the email
    // if there is no user with the email, create new user
    // else set the user data to token
   }

   return token;
  },

  async session({ session, token }) {
   if (token) {
    // set the token data to session
   }

   return session;
  },

  redirect() {
   return "/login";
  },
 },
});

Setting Up API Routes and Middleware

1. Create API Route for Authentication
Inside the app folder, create an api folder, then an auth folder, and finally a [...nextauth] folder inside it. Create a route.ts file inside the [...nextauth] folder with the following content:

// @/app/api/auth/[…nextauth]/route.ts

import { handlers } from "@/auth";

export const { GET, POST } = handlers;

2. Createroutes.tsin thesrcFolder
Create a routes.ts file inside the src folder with the following content:

// @/routes.ts

export const API_AUTH_PREFIX = "/api/auth";

export const AUTH_ROUTES = ["/login"];

export const PROTECTED_ROUTES = [
  "/",
  // your other protected routes
]

3. Createmiddleware.tsin thesrcFolderCreate a middleware.ts file inside the src folder with the following content:

// @/middleware.ts

import NextAuth from "next-auth";
import { NextResponse } from "next/server";

import { authConfig } from "@/lib/auth.config";
import { API_AUTH_PREFIX, AUTH_ROUTES, PROTECTED_ROUTES } from "@/routes";

export const { auth } = NextAuth(authConfig);

export default auth(req => {
 const pathname = req.nextUrl.pathname;

 // manage route protection
 const isAuth = req.auth;

 const isAccessingApiAuthRoute = pathname.startsWith(API_AUTH_PREFIX);
 const isAccessingAuthRoute = AUTH_ROUTES.some(route => pathname.startsWith(route));
 const isAccessingProtectedRoute = PROTECTED_ROUTES.some(route => pathname.startsWith(route));

 if (isAccessingApiAuthRoute) {
  return NextResponse.next();
 }

 if (isAccessingAuthRoute) {
  if (isAuth) {
   return NextResponse.redirect(new URL("/", req.url));
  }

  return NextResponse.next();
 }

 if (!isAuth && isAccessingProtectedRoute) {
  return NextResponse.redirect(new URL("/login", req.url));
 }
});

export const config = {
 matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};

This setup configures the database connection, authentication system, API routes, and middleware for your NextJS application.


Implementing Authentication Pages

1. Create the Login Page
Inside the app folder, create a login folder. Inside the login folder, create a page.tsx file with the following content:

// @/app/login/page.tsx

import { signIn } from "@/auth";

const LoginPage = () => {
 return (
   <form
     action={async () => {
       "use server";
       await signIn("google");
     }}
   >
     <button type="submit">Login with Google</button>
   </form>
   );
};

export default LoginPage;

2. Create the Home Page
Inside the app folder, create a page.tsx file with the following content:

// @/app/page.tsx

import { auth, signOut } from "@/auth";
import { notFound } from "next/navigation";

const HomePage = async () => {
 const session = await auth();
 if (!session) return notFound();
 return (
   <main>
     <h1>Hello {session.user.name}</h1>

     <form
       action={async () => {
         "use server";
         await signOut();
       }}
     >
       <button type="submit">Log Out</button>
     </form>
   </main>
 );
};
export default HomePage;

3. Run the Development Server
Run the following command in your terminal:

npm run dev

If everything is set up correctly, you will be asked to log in with your Google account. Once logged in, you should be able to see the home page with a greeting and an option to log out.


Conclusion

Implementing Google authentication in a Next.js 14 application using NextAuth.js 5 (beta), Prisma ORM, and MongoDB can be a streamlined and efficient process. By following the steps outlined in this article, you can set up a robust authentication system that leverages Google’s OAuth 2.0 for user authentication, Prisma for database management, and MongoDB as the database.

Here’s a brief recap of what we covered:

  1. Project Setup: Initializing a Next.js project and installing necessary dependencies.

  2. Google Auth Credentials: Configuring Google OAuth 2.0 credentials.

  3. Database Setup: Setting up a MongoDB database and configuring Prisma ORM.

  4. Prisma Configuration: Initializing Prisma and defining schema models for User and Account.

  5. Authentication Configuration: Setting up NextAuth.js configuration with Prisma adapter and custom callbacks.

  6. API Routes and Middleware: Defining API routes for authentication and implementing middleware for route protection.

  7. Authentication Pages: Creating login and home pages with server actions for sign-in and sign-out.

With this setup, you now have a fully functional authentication system integrated into your Next.js application. This foundation can be further extended to include more features such as authorization, role-based access control, and additional OAuth providers.

Feel free to customize and expand upon this setup to fit the specific needs of your application. For a complete reference and code implementation, you can visit the GitHub Repository.

Happy coding!


GitHub Repository

A

Your post is quite informative! It might be even more helpful if you could provide code examples for saving user information in a database and managing sessions.

3
S

I completely agree with you, but I haven't included that portion of the example because everyone saves their users in the database differently. Even so, the complete code may be found in the GitHub repository, which I have contributed. You are welcome to look through the repository.

https://github.com/SSazzadur/nextjs-google-auth