auth
Alasan ada: pendaftaran, login, dan sesi yang aman tanpa menulis ulang pengelolaan kata sandi, cookie, dan tabel sesi.
Mode: fullstack. Otomatis memasang db. (Untuk mode frontend dengan backend
terpisah, pakai bff-auth.)
npm create nextjs-kit@latest my-app -- --mode fullstack --modules authcp .env.example .env.localnpm run db:up && npm run db:migratenpm run devBuka /register untuk membuat akun, lalu /dashboard. /dashboard diproteksi; ubah daftar
route terproteksi di src/config/auth.ts.
Yang ditambahkan
Section titled “Yang ditambahkan”| Bagian | Isi |
|---|---|
src/server/auth/index.ts |
Konfigurasi Better Auth (adapter Drizzle, email dan kata sandi) |
src/server/auth/session.ts |
getSession() dan requireUser() |
src/server/db/auth-schema.ts |
Tabel user, session, account, verification |
drizzle/0001_auth.sql |
Migrasi untuk keempat tabel itu |
src/app/api/auth/[...all] |
Endpoint HTTP Better Auth |
src/features/auth |
Form masuk dan daftar, tombol keluar |
src/proxy.ts |
Pagar optimis untuk route terproteksi |
e2e/auth.spec.ts |
E2E: daftar, masuk, keluar, rate limit |
Melindungi data
Section titled “Melindungi data”import { requireUser } from "@/server/auth/session";
export default async function Page() { const user = await requireUser(); // ...}proxy.ts hanya mengecek keberadaan cookie sesi dan tidak menyentuh database, jadi cookie palsu
lolos dari sana. requireUser() yang memvalidasi sesi. Pakai di halaman, Server Action, dan
DAL yang butuh login.
Kenapa klien Better Auth, bukan Server Action
Section titled “Kenapa klien Better Auth, bukan Server Action”Form memanggil authClient (HTTP ke /api/auth/*), tidak memanggil auth.api.signInEmail dari
Server Action. Alasannya keamanan: rate limit dan pengecekan origin Better Auth berjalan di lapisan
HTTP, sehingga pemanggilan langsung dari server melewatinya dan login jadi bisa di-brute-force.
Ini sedikit menyimpang dari pola “mutasi = Server Action” di tempat lain.
Rate limit dan IP klien
Section titled “Rate limit dan IP klien”Percobaan /sign-in dan /sign-up dibatasi 3 permintaan per 10 detik per IP (aktif di mode
production). Agar itu bekerja, Better Auth harus bisa menentukan IP klien yang tepercaya. Kalau
tidak, semua pengguna berbagi satu bucket, sehingga siapa pun bisa mengunci login orang lain.
Better Auth membaca x-forwarded-for:
- Tanpa konfigurasi, header harus berisi tepat satu IP valid. Di nginx, timpa header itu:
Jangan pakaiproxy_set_header X-Forwarded-For $remote_addr;
$proxy_add_x_forwarded_fortanpaAUTH_TRUSTED_PROXIES, karena header menjadi rantai (klien, proxy) dan IP tidak bisa ditentukan. - Atau isi
AUTH_TRUSTED_PROXIESdengan IP atau CIDR proxy Anda (dipisah koma). Better Auth lalu membaca rantai dari kanan, melewati proxy tepercaya, dan memakai IP klien yang sebenarnya.
Aplikasi sebaiknya hanya bisa dijangkau lewat proxy itu. Kalau terbuka langsung ke internet,
klien bisa memalsukan x-forwarded-for dan melewati rate limit.
Penyimpanan rate limit bawaan ada di memori proses, jadi tidak dibagi antar instance. Untuk beberapa instance, pindahkan ke database atau penyimpanan bersama (lihat dokumentasi Better Auth).
Environment
Section titled “Environment”| Variabel | Default | Keterangan |
|---|---|---|
BETTER_AUTH_SECRET |
Hanya saat dev dan test | Minimal 32 karakter. Wajib di production: build dan start gagal bila kosong. Buat dengan openssl rand -base64 32 |
AUTH_TRUSTED_PROXIES |
kosong | IP atau CIDR reverse proxy, dipisah koma |
NEXT_PUBLIC_APP_URL |
http://localhost:3000 |
Dipakai sebagai baseURL; harus sama dengan origin yang dibuka pengguna |
Nilai bawaan BETTER_AUTH_SECRET untuk dev tidak aman dan sengaja tidak berlaku di production.
Catatan
Section titled “Catatan”- Migrasi
0001_authdibuat dengandrizzle-kitdi atas migrasidb. Modul ini menimpadrizzle/meta/_journal.jsondengan versi yang memuat kedua migrasi. auth-schema.test.tsmembandingkan tabel Drizzle dengan definisi dari paketbetter-auth; kalau paket diperbarui dan menambah field, test gagal sebelum login rusak di runtime.- Verifikasi email, reset kata sandi, dan login sosial belum disertakan.
- Bersama
dal, todos menjadi milik per pengguna (lihat bagian itu). - CI proyek selalu menyiapkan Postgres dan menjalankan migrasi untuk E2E auth. Script
test:dbhanya dijalankan bila moduldaljuga terpasang.