NOMUD Dev Blog
HomeAuthor

Integrate Auth.js (>5.0) and Prisma into Next.js

Published in Web Dev
July 16, 2024
1 min read

Table Of Contents

01
Installing Auth.js
02
Setup Environment
03
Configure
04
Prisma Adapter Integration
05
Nodemailer Setup
06
Reference

Installing Auth.js

  1. run yarn add next-auth@beta

Setup Environment

  1. run npx auth secret, after this, AUTH_SECRET will be added to your .env.local file.

Configure

  1. Start by creating a new auth.ts file at the root of your app with the following content.
import NextAuth from "next-auth"
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [],
})
  1. Add the following to the tsconfig.json file in your root folder.
{
"compilerOptions": {
"paths": {
"@/auth": ["./auth.ts"],
...
}
},
...
}
  1. Add a Route Handler under /app/api/auth/[…nextauth]/route.ts.
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers
  1. Add optional Middleware to keep the session alive, this will update the session expiry every time its called.
export { auth as middleware } from "@/auth"

Prisma Adapter Integration

1. Installation

yarn add @prisma/client @auth/prisma-adapter
yarn add prisma --dev

2. Environment Variables

DATABASE_URL=postgres://postgres:adminadmin@0.0.0.0:5432/db

3. Init PrismaClient

Create the file ./clients/prisma.ts with the following, add the path to the tsconfig.json file in your root folder.

import { PrismaClient } from "@prisma/client"
const prismaClientSingleton = () => {
return new PrismaClient()
}
declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>
} & typeof global
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()
export default prisma
if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma

4. Configuration

import NextAuth from "next-auth"
import prisma from "@/clients/prisma"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [],
})

5. Create Schema

Create a schema file at prisma/schema.prisma with the following ProsgreSQL.

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])
}

6. Apply Schema

yarn prisma migrate dev

Nodemailer Setup

1. Install Nodemailer

yarn add nodemailer

2. SMTP Transport Configuration

// .env.local
EMAIL_SERVER_USER=username
EMAIL_SERVER_PASSWORD=password
EMAIL_SERVER_HOST=smtp.example.com
EMAIL_SERVER_PORT=587
EMAIL_FROM=noreply@example.com
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import prisma from "@/clients/prisma"
import Nodemailer from "next-auth/providers/nodemailer"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
Nodemailer({
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,
}),
],
})

3. Signin Button

Next, we can add a sign in button somewhere in your application like the Navbar. This will forward the user on to the Auth.js default signin page.

import { signIn } from "../../auth.ts"
export function SignIn() {
return (
<form
action={async () => {
"use server"
await signIn()
}}
>
<button type="submit">Sign In</button>
</form>
)
}

4. Signin

Start your application, click on the sign in button we just added, and you should see Auth.js built-in sign in page with the option to sign in with your email: image Insert your email and click “Sign in with Email”. You should receive an email from Auth.js, click on it and should be redirected to your application, landing already authenticated.

Reference

  • Auth.js | Installation
  • Auth.js | Prisma
  • Auth.js | Nodemailer Setup
  • Prisma Documentation | Best practice for instantiating Prisma Client with Next.js

Tags

#nextjs#authjs#prisma

Share

Previous Article
Resolving "Cannot find module 'next/babel'" in Next.js

Related Posts

Resolving "Cannot find module 'next/babel'" in Next.js
July 10, 2024
1 min
© 2024, All Rights Reserved.