Next.js 14 Authentication Menggunakan Prisma dan Auth.js: A Complete Guide

5 min read
·

Autentikasi adalah bagian penting dari setiap aplikasi web. Auth.js memungkinkan user untuk login, membuat akun, dan mengakses konten.

Next.js 14 App Router dan Auth.js masih baru dan belum banyak tutorial yang menjelaskan cara mengimplementasikannya. Next.js App Router adalah router baru yang dibangun di atas Next.js Router — ini memberikan cara yang lebih sederhana dan intuitif untuk menangani routing dalam aplikasi Next.js. Auth.js adalah library yang menyediakan fungsionalitas autentikasi dan otorisasi untuk aplikasi Next.js. Auth.js masih dalam beta, artinya tidak siap untuk digunakan dalam production. Jadi, berhati-hatilah saat menggunakannya dalam production.

Dalam tutorial ini, kita akan belajar cara mengimplementasikan autentikasi menggunakan Next.js dan Auth.js. Kita akan menggunakan Google sebagai auth provider kita dan Prisma sebagai ORM kita.

Sebelum Memulai

Sebelum kita memulai, pastikan kamu telah setup & install:

  • Node.js 18.18 atau versi yang lebih baru terinstal di PC kamu
  • PostgreSQL
  • Code Editor atau IDE

Menyiapkan Projek

Buat projek Next.js baru menggunakan perintah berikut:

Terminal window
npx create-next-app@latest

Ini akan membuat projek Next.js dengan dependensi dan konfigurasi yang diperlukan.

Menginstal Prisma & Auth.js

Untuk menginstal Prisma ORM dan Auth.js, jalankan perintah berikut:

Terminal window
npm install next-auth@beta
npm install @prisma/client @auth/prisma-adapter
npm install prisma --save-dev
# Generate auth secret
npx auth secret
# Set up Prisma
npx prisma init

Ini akan membuat file baru bernama schema/schema.prisma di projek kamu.

Konfigurasi Prisma

Hapus file .env.local karena Prisma tidak mendukung sintaks .env.local.

Buka file .gitignore dan tambahkan:

.gitignore
.env

Buka file .env dan modifikasi kode berikut:

.env
DATABASE_URL=postgres://postgres:[email protected]:5432/db

Modifikasi DATABASE_URL dengan url database kamu. Jangan lupa untuk mengganti /db dengan nama database atau schema kamu.

Kemudian, tambahkan kode berikut ke schema/schema.prisma file:

schema/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Account {
id String @id @default(cuid())
userId String @map("user_id")
type String
provider String
providerAccountId String @map("provider_account_id")
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@map("accounts")
}
model Session {
id String @id @default(cuid())
sessionToken String @unique @map("session_token")
userId String @map("user_id")
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime? @map("email_verified")
image String?
accounts Account[]
sessions Session[]
// Optional for WebAuthn support
Authenticator Authenticator[]
@@map("users")
}
model VerificationToken {
identifier String
token String
expires DateTime
@@unique([identifier, token])
@@map("verificationtokens")
}
// Optional for WebAuthn support
model Authenticator {
credentialID String @unique @map("credential_id")
userId String @map("user_id")
providerAccountId String @map("provider_account_id")
credentialPublicKey String @map("credential_public_key")
counter Int
credentialDeviceType String @map("credential_device_type")
credentialBackedUp Boolean @map("credential_backed_up")
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([userId, credentialID])
@@map("authenticators")
}

Jalankan migrasi menggunakan:

Terminal window
# migrate the database
npm exec prisma migrate dev
# generate the prisma client
npm exec prisma generate

Konfigurasi Auth.js

Buat file bernama auth.ts di root project dan tambahkan kode berikut:

auth.ts
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
import Google from "next-auth/providers/google"
const prisma = new PrismaClient()
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [Google],
})

Buat dan modifikasi file berikut:

app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers

Mendaftarkan klien OAuth Google

Sebelum kita dapat menggunakan Google sebagai provider autentikasi kami, kita perlu mendaftarkan klien OAuth Google.

  1. Buka Google Cloud Console dan buat projek baru.
  2. Pergi ke API dan Layanan dan aktifkan Google Identity and Access Management (IAM) API.
  3. Pergi ke Pengidentifikasi dan akses dan buat klien OAuth baru.
  4. Isi Authorized JavaScript origins dengan http://localhost:3000
  5. Isi Authorized redirect URIs dengan
http://localhost:3000/api/auth/callback/google
  1. Klik Save
  2. Salin Client ID dan Client Secret dan tambahkan ke .env file kamu.
.env
AUTH_GOOGLE_ID=YOUR_CLIENT_ID
AUTH_GOOGLE_SECRET=YOUR_CLIENT_SECRET

Menerapkan autentikasi

Sekarang kita telah mempunyai fungsi signIn, kita dapat mengimplementasikan autentikasi di aplikasi. Untuk itu, kita akan menggunakan fungsi ini untuk masuk ke dalam aplikasi.

Buatlah halaman login sederhana.

app/login/page.tsx
import { signIn } from "@/auth"
export default function SignIn() {
return (
<form
className="flex flex-col items-center justify-center gap-4 p-8 text-center"
action={async () => {
"use server"
await signIn("google", {
redirectTo: "/protected",
})
}}
>
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Signin with Google
</button>
</form>
)
}

Buatlah protected page.

app/protected/page.tsx
import { auth, signOut } from "@/auth"
export default async function ProtectedPage() {
const session = await auth()
if (!session) {
return (
<div className="flex flex-col items-center justify-center gap-4 p-8 text-center">
<h1>Protected Page</h1>
<p>You are not signed in</p>
<a href="/login">
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Signin
</button>
</a>
</div>
)
}
return (
<div className="flex flex-col items-center justify-center gap-4 p-8 text-center">
<h1>Protected Page</h1>
<p>You are signed in as {session.user!.email}</p>
<form
action={async () => {
"use server"
await signOut()
}}
>
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Signout
</button>
</form>
</div>
)
}

Melakukan Testing

Sejauh ini, kita telah mengimplementasikan fungsi signIn untuk mengautentikasi user. Sekarang, mari kita uji coba.

Case 1: Login dengan user yang belum login

  1. Buka halaman login: http://localhost:3000/login
  2. Klik tombol Signin with Google
  3. Halaman Google login akan muncul.
  4. Masukkan kredensial akun Google kamu dan klik “Allow”.
  5. Kamu akan di redirect ke http://localhost:3000/protected.
  6. Kamu akan melihat halaman protected dengan pesan You are signed in as {email_kamu}

Case 2: Memasuki halaman protected dengan user yang belum login

  1. Buka halaman protected: http://localhost:3000/protected
  2. Kamu akan melihat halaman protected dengan pesan You are not signed in

Kesimpulan

Di tutorial ini, kita belajar bagaimana mengimplementasikan autentikasi menggunakan Next.js dan Auth.js. Kita mengatur projek, menginstal Auth.js, dan mengkonfigurasikannya untuk bekerja dengan Next.js. Kita juga belajar bagaimana mengatur Prisma, Auth.js, dan Next.js untuk working together. Lalu, kita mengimplementasikan autentikasi di aplikasi kita dengan menggunakan auth method untuk memeriksa apakah pengguna sudah terautentikasi dan menampilkan konten yang tidak terautentikasi jika mereka belum login.

Saya harap tutorial ini bermanfaat dan memudahkan kamu dalam memahami bagaimana mengimplementasikan autentikasi menggunakan Next.js dan Auth.js.

What’s next?

Di tutorial berikutnya, kita akan belajar bagaimana mengimplementasikan authorization menggunakan Next.js dan Auth.js. Kita akan menggunakan objek user untuk memeriksa apakah pengguna memiliki izin yang diperlukan untuk mengakses halaman atau resource tertentu.

Jika kamu punya pertanyaan atau saran, bisa menghubungi saya melalui GitHub atau Twitter. Stay tuned untuk tutorial lebih lanjut tentang konsep advance Next.js dan Auth.js!