SJ Logo
Now Learning
rust

Setup OAuth with NextAuth , Prisma and Postgres

2024-10-23

Setting up NextAuth with Google, Discord, and GitHub OAuth , Prisma , Postgres .

Step 1: Set up PostgreSQL Database Locally

First, create a compose.yaml file to define your PostgreSQL service:

version: '3.8'

services:
  database:
    image: postgres:latest
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: pgdb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  postgres_data:

To start the database:

Your database URL will look like this:

postgresql://admin:password@localhost:5432/pgdb

This is the DB URL : postgresql://<user>:<password>@localhost:<port>/<dbname>

Step 2: Set Up Google OAuth

  1. Visit Google's API Dashboard and create a new project.

A screenshot of google's website API dashboard

  1. In the project, navigate to the Credentials tab.

A screenshot of google's oauth credentials tab

  1. Click Create Credentials and select OAuth client ID.

A ss of oauth ,click on create creds , click on oauth id

  1. Under Application type, select Web Application.

A ss of oauth ,click on Application type , click on website

  1. Fill in the details:
    • Authorized JavaScript origins: http://localhost:3000
    • Authorized redirect URIs: http://localhost:3000/api/auth/callback/google

step 5

  1. Copy the Client ID and Client Secret.

  2. Create a .env.local file in your project root and add the following:

GOOGLE_CLIENT_ID="Paste your Google client ID here"
GOOGLE_CLIENT_SECRET="Paste your Google client secret here"

Step 3: Set Up Discord OAuth

  1. Visit the Discord Developer Portal and create a new application.

Discord oauth home

Create application discord oauth

  1. Select the OAuth2 tab.

screenshot of clicking on oauth2 tab

  1. Under Redirects, add the following:
    • http://localhost:3000/api/auth/callback/discord

alt text

  1. Copy the Client ID and Client Secret.

  2. Add the following to your .env.local file:

DISCORD_CLIENT_ID="Paste your Discord client ID here"
DISCORD_CLIENT_SECRET="Paste your Discord client secret here"

Step 4: Set Up GitHub OAuth (Optional)

  1. Visit GitHub Developer Settings and create a new OAuth application.

  2. Fill out the following details:

    • Homepage URL: http://localhost:3000
    • Authorization callback URL: http://localhost:3000/api/auth/callback/github
  3. Copy the Client ID and Client Secret.

  4. Add the following to your .env.local file:

GITHUB_CLIENT_ID="Paste your GitHub client ID here"
GITHUB_CLIENT_SECRET="Paste your GitHub client secret here"

Final .env.local File Example:

GOOGLE_CLIENT_ID="Paste your Google client ID here"
GOOGLE_CLIENT_SECRET="Paste your Google client secret here"

DISCORD_CLIENT_ID="Paste your Discord client ID here"
DISCORD_CLIENT_SECRET="Paste your Discord client secret here"

GITHUB_CLIENT_ID="Paste your GitHub client ID here"
GITHUB_CLIENT_SECRET="Paste your GitHub client secret here"

DATABASE_URL="postgresql://admin:password@localhost:5432/pgdb"

Step 5: Set Up NextAuth in Your Application

Install the necessary dependencies:

npm install next-auth

Step 6: Setting Up Prisma with NextAuth

To configure Prisma with your NextAuth setup, follow the steps below:

  1. Install Prisma and the Prisma adapter:

Run the following commands to install Prisma and its client, along with the NextAuth Prisma adapter:

npm install @prisma/client @auth/prisma-adapter
npm install prisma --save-dev
  1. Initialize Prisma:

Run the following command to initialize Prisma in your project:

npx prisma init

This will create a prisma folder with a schema.prisma file and a .env file.

Step 7: Modify Prisma Schema

In the prisma/schema.prisma file, modify it to define the User, Account, Session, and VerificationToken models as needed by NextAuth:

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

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[]
  // Optional for WebAuthn support
  Authenticator Authenticator[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Account {
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String?
  access_token      String?
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String?
  session_state     String?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@id([provider, providerAccountId])
}

model Session {
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model VerificationToken {
  identifier String
  token      String
  expires    DateTime

  @@id([identifier, token])
}

// Optional for WebAuthn support
model Authenticator {
  credentialID         String  @unique
  userId               String
  providerAccountId    String
  credentialPublicKey  String
  counter              Int
  credentialDeviceType String
  credentialBackedUp   Boolean
  transports           String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@id([userId, credentialID])
}

Step 8: Run Migrations

Once the schema is set, you'll need to create and apply a migration to your database:

npx prisma migrate dev --name init

This will generate the necessary tables in your database based on the schema defined above.

Step 9: Set Up Prisma Client and NextAuth

Now, you'll set up Prisma to avoid creating multiple instances across your project:

  1. Create a prisma.ts file:

In your project, create a prisma.ts file to instantiate Prisma:

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

const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };

export const prisma = globalForPrisma.prisma || new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
  1. Set up NextAuth with Prisma Adapter:

In your auth.ts or route.ts file for NextAuth (using the Next.js 13.2 Route Handlers), initialize NextAuth with the Prisma adapter:

// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/prisma";

const handler = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
       GoogleProvider({          
          clientId: process.env.GOOGLE_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      }),
      DiscordProvider({
        clientId: process.env.DISCORD_CLIENT_ID!,
        clientSecret: process.env.DISCORD_CLIENT_SECRET!,
        authorization: {params: {scope: scopes.join(' ')}},
      }),
      GithubProvider({
        clientId: process.env.GITHUB_CLIENT_ID!,
        clientSecret: process.env.GITHUB_CLIENT_SECRET!,
      })
  ],
});

export { handler as GET, handler as POST };

Final Steps

  1. Update the .env file:

Ensure that your .env file has the correct database connection string:

DATABASE_URL="postgresql://admin:password@localhost:5432/pgdb"
  1. Run the Development Server:

After setting everything up, run your Next.js app:

npm run dev

Now your app is configured to use NextAuth with Google, Discord, GitHub OAuth, and Prisma ORM with PostgreSQL.