DEV Community

Cover image for NextAuth.js+App Router+Prisma
Ken Obara
Ken Obara

Posted on

NextAuth.js+App Router+Prisma

When you want to add authentication to Next.js app, NextAuth.js is a good helper. This article shows the simple app with Next.js(App Router), NextAuth.js, Prisma, TypeScript, SQLite, GitHub OAuth.

This article libraries versions

Node.js 20.10.0
Next.js 14.0.4
NextAuth.js 5.0.0-beta.4

Next.js

Install Next.js

npx create-next-app@latest authjs-approuter-prisma-app
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like to use `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to customize the default import alias (@/*)? … No
Enter fullscreen mode Exit fullscreen mode

NextAuth.js

Install NextAuth.js

npm install next-auth@beta
Enter fullscreen mode Exit fullscreen mode

Add auth.ts file

// auth.ts
import NextAuth from "next-auth";

import GitHub from "next-auth/providers/github";
import type { NextAuthConfig } from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export const config = {
  adapter: PrismaAdapter(prisma),
  providers: [GitHub],
  callbacks: {
    authorized({ request, auth }) {
      const { pathname } = request.nextUrl;
      if (pathname === "/middleware-example") return !!auth;
      return true;
    },
  },
} satisfies NextAuthConfig;

export const { handlers, auth, signIn, signOut } = NextAuth(config);
Enter fullscreen mode Exit fullscreen mode

Add route.ts file

// src/app/api/auth/[...nextauth]/route.ts
import { handlers } from "../../../../../auth";
export const { GET, POST } = handlers;
Enter fullscreen mode Exit fullscreen mode

Add Middleware settings

// middleware.ts
export { auth as middleware } from "./auth";

// Read more: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};
Enter fullscreen mode Exit fullscreen mode

Prisma

Install Prisma and initialize

npm install prisma --save-dev
npx prisma init --datasource-provider sqlite # MySQL or PostgreSQL instead of SQLite
Enter fullscreen mode Exit fullscreen mode

NextAuth/Prisma

Install Prisma Adapter

npm install @prisma/client @auth/prisma-adapter
Enter fullscreen mode Exit fullscreen mode

Add Prisma schema

// prisma/schema.prisma
datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

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

model Account {
  id                 String  @id @default(cuid())
  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?

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

  @@unique([provider, providerAccountId])
}

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

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}
Enter fullscreen mode Exit fullscreen mode

Migrate Schema

npx prisma migrate dev
Enter fullscreen mode Exit fullscreen mode

GitHub OAuth

This chapter shows how to set GitHub Key.

Go to this link
https://github.com/settings/applications/new

Register a new OAuth application
Image description

Generate a client secret
Image description

Generate a secret for AUTH_SECRET

openssl rand -base64 32
# Xh0Pvfu4VQsM+MEGw47Zo84eOZejKgjbL7XwdCyFQhM=
Enter fullscreen mode Exit fullscreen mode

Set environment variables

# .env.local
AUTH_SECRET=Xh0Pvfu4VQsM+MEGw47Zo84eOZejKgjbL7XwdCyFQhM=

AUTH_GITHUB_ID=b9cb58b0c451fd68e1a2
AUTH_GITHUB_SECRET=2da087aed1d6ec3ec6509531c697d7d91eb0a112
Enter fullscreen mode Exit fullscreen mode

Screen

Change appearance

// src/app/page.tsx
import { auth, signIn, signOut } from "../../auth";

export default async function Home() {
  const session = await auth();
  if (!session?.user)
    return (
      <div className="m-48">
        <SignIn />
      </div>
    );

  return (
    <div className="m-48">
      <p>{session.user.name}</p>
      <p>{session.user.email}</p>
      <SignOut />
    </div>
  );
}

export function SignIn() {
  return (
    <form
      action={async () => {
        "use server";
        await signIn();
      }}
    >
      <button>Sign In</button>
    </form>
  );
}

export function SignOut() {
  return (
    <form
      action={async () => {
        "use server";
        await signOut();
      }}
    >
      <button>Sign Out</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Let's run app

Let's check the app

npm run dev
Enter fullscreen mode Exit fullscreen mode

http://localhost:3000/

Image description

Image description

Image description

npx prisma studio
Enter fullscreen mode Exit fullscreen mode

Image description

Reference

https://github.com/nextauthjs/next-auth-example
https://next-auth.js.org/getting-started/example
https://next-auth.js.org/configuration/initialization#route-handlers-app
https://www.prisma.io/docs/getting-started/quickstart
https://authjs.dev/reference/adapter/prisma

Top comments (0)