Next.js 14 Authentication Menggunakan Prisma dan Auth.js: A Complete Guide
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:
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:
npm install next-auth@betanpm install @prisma/client @auth/prisma-adapternpm install prisma --save-dev
# Generate auth secretnpx auth secret
# Set up Prismanpx 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:
.env
Buka file .env
dan modifikasi kode berikut:
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:
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 supportmodel 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:
# migrate the databasenpm exec prisma migrate dev
# generate the prisma clientnpm exec prisma generate
Konfigurasi Auth.js
Buat file bernama auth.ts
di root project dan tambahkan kode berikut:
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:
import { handlers } from "@/auth" // Referring to the auth.ts we just createdexport const { GET, POST } = handlers
Mendaftarkan klien OAuth Google
Sebelum kita dapat menggunakan Google sebagai provider autentikasi kami, kita perlu mendaftarkan klien OAuth Google.
- Buka Google Cloud Console dan buat projek baru.
- Pergi ke API dan Layanan dan aktifkan Google Identity and Access Management (IAM) API.
- Pergi ke Pengidentifikasi dan akses dan buat klien OAuth baru.
- Isi Authorized JavaScript origins dengan
http://localhost:3000
- Isi Authorized redirect URIs dengan
http://localhost:3000/api/auth/callback/google
- Klik Save
- Salin Client ID dan Client Secret dan tambahkan ke
.env
file kamu.
AUTH_GOOGLE_ID=YOUR_CLIENT_IDAUTH_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.
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.
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
- Buka halaman login: http://localhost:3000/login
- Klik tombol Signin with Google
- Halaman Google login akan muncul.
- Masukkan kredensial akun Google kamu dan klik “Allow”.
- Kamu akan di redirect ke http://localhost:3000/protected.
- Kamu akan melihat halaman protected dengan pesan You are signed in as {email_kamu}
Case 2: Memasuki halaman protected dengan user yang belum login
- Buka halaman protected: http://localhost:3000/protected
- 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!