Autentikasi adalah fitur wajib di hampir setiap aplikasi, tapi juga salah satu yang paling membosankan dan rawan kesalahan untuk dibuat dari nol. Mengurus hashing password, manajemen sesi, dan keamanan adalah pekerjaan besar.
Bagaimana jika Anda bisa mengimplementasikan login via Google, GitHub, dan bahkan login tanpa password (magic link) hanya dalam hitungan menit? Mari kita lakukan dengan Supabase, sebuah alternatif Firebase open-source yang powerful.
Dalam tutorial ini, kita akan membangun sistem autentikasi lengkap di aplikasi Next.js dari awal.
Prasyarat (Prerequisites)
Sebelum memulai, pastikan Anda sudah menyiapkan hal-hal berikut:
- Akun Supabase: Anda bisa mendaftar gratis di supabase.com.
- Akun Google: Dibutuhkan untuk membuat kredensial di Google Cloud Console.
- Node.js dan npm/yarn: Pastikan sudah terinstall di komputer Anda.
- Pengetahuan Dasar React & Next.js: Tutorial ini mengasumsikan Anda sudah familiar dengan komponen dan hooks di React/Next.js.
Memahami Struktur Folder Proyek
Sebelum kita mulai menulis kode, mari kita lihat struktur folder yang akan kita bangun. Ini akan membantu Anda memahami di mana setiap file berada dan apa fungsinya.
supabase-auth-tutorial/
├── app/
│ ├── dashboard/
│ │ └── page.tsx # Halaman yang dilindungi (/dashboard)
│ ├── layout.tsx # Layout utama aplikasi
│ └── page.tsx # Halaman utama (homepage, /)
│
├── components/
│ └── AuthUI.tsx # Komponen UI untuk login dan logout
│
├── lib/
│ └── supabaseClient.ts # File untuk inisialisasi client Supabase
│
├── .env.local # Menyimpan kredensial rahasia
├── next.config.mjs # Konfigurasi Next.js
└── package.json # Daftar dependensi dan skrip proyek
Secara singkat, app/
menangani rute, components/
menyimpan UI yang dapat digunakan kembali, lib/
berisi koneksi ke Supabase, dan .env.local
menjaga keamanan kredensial kita.
Mari kita mulai membangunnya.
Langkah 1: Setup Proyek Supabase
Pertama, kita perlu membuat proyek di Supabase untuk mendapatkan kredensial API.
- Buka dashboard Supabase dan klik “New Project”.
- Isi nama proyek dan buat password database yang kuat. Pilih region yang terdekat dengan Anda.
- Tunggu beberapa menit hingga proyek Anda selesai dibuat.
- Setelah selesai, navigasi ke Project Settings (ikon roda gigi di sidebar kiri).
- Pilih menu API. Di sini Anda akan menemukan dua hal penting: Project URL dan Project API Keys (kita akan menggunakan
anon
key).
Penting:
anon
key aman untuk diekspos di sisi klien (browser), tetapiservice_role
key harus dijaga kerahasiaannya dan tidak boleh digunakan di frontend.
Langkah 2: Integrasi Supabase ke Proyek Next.js
Sekarang, mari kita siapkan proyek Next.js dan hubungkan dengan Supabase.
-
Buat proyek Next.js baru jika Anda belum punya:
npx create-next-app@latest supabase-auth-tutorial
-
Masuk ke direktori proyek dan install library Supabase:
cd supabase-auth-tutorial npm install @supabase/supabase-js
-
Simpan Kredensial dengan Aman: Buat file bernama
.env.local
di root proyek Anda dan tambahkan kredensial Supabase.NEXT_PUBLIC_SUPABASE_URL=URL_PROYEK_ANDA NEXT_PUBLIC_SUPABASE_ANON_KEY=ANON_KEY_ANDA
Ganti
URL_PROYEK_ANDA
danANON_KEY_ANDA
dengan nilai yang Anda dapatkan dari Langkah 1. -
Buat Supabase Client: Buat folder
lib
di root proyek, lalu buat filesupabaseClient.ts
di dalamnya. Ini adalah tempat kita menginisialisasi Supabase.// lib/supabaseClient.ts import { createClient } from '@supabase/supabase-js' const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! export const supabase = createClient(supabaseUrl, supabaseAnonKey)
Langkah 3: Implementasi Social Login (Login dengan Google)
Ini adalah cara termudah bagi pengguna untuk masuk ke aplikasi Anda. Proses ini memerlukan beberapa langkah konfigurasi di Google Cloud Console untuk mendapatkan kredensial Anda sendiri.
3.1: Konfigurasi Proyek di Google Cloud Console
- Buka Google Cloud Console: Kunjungi console.cloud.google.com.
- Buat Proyek Baru: Klik menu dropdown proyek > “New Project”. Beri nama yang relevan (misal: “Supabase Auth App”), lalu Create.
- Konfigurasi Layar Izin OAuth:
- Dari menu navigasi, pergi ke APIs & Services > OAuth consent screen.
- Pilih tipe pengguna “External” dan klik Create.
- Isi informasi yang diperlukan: App name, User support email, dan Developer contact information.
- Klik Save and Continue hingga selesai.
- Buat Kredensial OAuth 2.0:
- Pergi ke APIs & Services > Credentials.
- Klik + CREATE CREDENTIALS > “OAuth client ID”.
- Pilih “Web application” sebagai Application type.
- Di bagian “Authorized redirect URIs”, klik + ADD URI. Ini adalah bagian paling penting. Masukkan URI callback dari Supabase dengan format:
Gantihttps://<PROJECT_REFERENCE_ID>.supabase.co/auth/v1/callback
<PROJECT_REFERENCE_ID>
dengan ID proyek Supabase Anda (ditemukan di Project Settings > General).
- Salin Kredensial Anda: Setelah mengklik Create, sebuah popup akan muncul menampilkan Your Client ID dan Your Client Secret. Salin kedua nilai ini.
3.2: Masukkan Kredensial ke Supabase
- Kembali ke dashboard Supabase Anda, buka Authentication > Providers.
- Pilih Google, aktifkan, lalu tempel (paste) Client ID dan Client Secret yang Anda dapatkan dari Google.
- Klik Save.
3.3: Tambahkan Kode Login di Next.js
Fungsi untuk memanggil Google Auth tetap sederhana. Kita akan menempatkannya di komponen AuthUI
nanti.
async function signInWithGoogle() {
await supabase.auth.signInWithOAuth({
provider: 'google',
options: { redirectTo: window.location.origin }
});
}
Langkah 4: Implementasi Passwordless Login (Magic Link)
Magic Link adalah metode login di mana pengguna hanya perlu memasukkan email untuk menerima tautan login unik.
Fungsi untuk ini juga sederhana dan akan kita letakkan di komponen AuthUI
.
async function signInWithMagicLink(email: string) {
await supabase.auth.signInWithOtp({
email: email,
options: { emailRedirectTo: window.location.origin },
});
alert('Link login telah dikirim ke email Anda!');
}
Langkah 5: Mengelola Sesi Pengguna (Komponen AuthUI)
Saatnya menyatukan semuanya dalam satu komponen AuthUI.tsx
.
-
Buat file
components/AuthUI.tsx
. -
Isi dengan kode berikut:
// components/AuthUI.tsx 'use client'; import { useState, useEffect } from 'react'; import { supabase } from '../lib/supabaseClient'; import type { Session } from '@supabase/supabase-js'; export default function AuthUI() { const [session, setSession] = useState<Session | null>(null); const [email, setEmail] = useState(''); useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); }); const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => { setSession(session); }); return () => subscription.unsubscribe(); }, []); async function signInWithGoogle() { await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: window.location.origin } }); } async function handleMagicLinkLogin(e: React.FormEvent) { e.preventDefault(); try { await supabase.auth.signInWithOtp({ email, options: { emailRedirectTo: window.location.origin }, }); alert('Link login telah dikirim ke email Anda!'); } catch (error) { console.error('Error:', error); alert('Gagal mengirim link.'); } } async function handleLogout() { await supabase.auth.signOut(); setSession(null); } if (!session) { return ( <div className="w-full max-w-sm p-8 space-y-6 bg-white rounded-lg shadow-md"> <h2 className="text-2xl font-bold text-center">Login</h2> <button onClick={signInWithGoogle} className="w-full px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700" > Login dengan Google </button> <div className="my-4 text-center text-gray-500">atau</div> <form onSubmit={handleMagicLinkLogin} className="space-y-4"> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="your.email@example.com" className="w-full p-2 border rounded" required /> <button type="submit" className="w-full px-4 py-2 font-semibold text-white bg-green-500 rounded hover:bg-green-700"> Kirim Link Login </button> </form> </div> ); } return ( <div className="w-full max-w-sm p-8 text-center bg-white rounded-lg shadow-md"> <h2 className="text-xl font-bold">Selamat Datang!</h2> <p className="my-4">Anda login sebagai: <strong>{session.user.email}</strong></p> <button onClick={handleLogout} className="w-full px-4 py-2 font-semibold text-white bg-red-500 rounded hover:bg-red-700" > Logout </button> </div> ); }
-
Gunakan komponen ini di halaman utama Anda (
app/page.tsx
).// app/page.tsx import AuthUI from '../components/AuthUI'; export default function Home() { return ( <main className="flex items-center justify-center min-h-screen bg-gray-100"> <AuthUI /> </main> ); }
Langkah 6: (Opsional) Melindungi Halaman (Protected Routes)
Untuk halaman /dashboard
yang hanya bisa diakses oleh pengguna yang sudah login:
-
Buat file
app/dashboard/page.tsx
. -
Gunakan
useEffect
untuk memeriksa sesi dan mengarahkan pengguna jika belum login.// app/dashboard/page.tsx 'use client'; import { useEffect, useState } from 'react'; import { supabase } from '../../lib/supabaseClient'; import { useRouter } from 'next/navigation'; import type { User } from '@supabase/supabase-js'; export default function Dashboard() { const [user, setUser] = useState<User | null>(null); const [loading, setLoading] = useState(true); const router = useRouter(); useEffect(() => { async function getUser() { const { data: { user } } = await supabase.auth.getUser(); if (!user) { router.push('/'); // Redirect jika tidak ada user } else { setUser(user); } setLoading(false); } getUser(); }, [router]); if (loading) { return <p className="text-center">Loading...</p>; } if (user) { return ( <div className="p-8"> <h1 className="text-3xl font-bold">Dashboard Pribadi</h1> <p>Halo, {user.email}! Ini adalah halaman rahasia Anda.</p> </div> ); } return null; }
Kesimpulan
Selamat! Anda telah berhasil membangun sistem autentikasi yang modern, aman, dan mudah digunakan dengan Supabase di aplikasi Next.js Anda. Kita telah mengimplementasikan Social Login (Google) dan Passwordless Login (Magic Link), serta cara mengelola sesi dan melindungi halaman.
Supabase Auth menawarkan lebih banyak lagi, seperti login dengan password tradisional, autentikasi via GitHub atau provider lain, dan manajemen pengguna yang lengkap. Ini adalah fondasi yang kokoh untuk membangun aplikasi web yang aman.
Untuk referensi, Anda dapat melihat kode final dari tutorial ini di repositori GitHub berikut: Source code lengkap
Jika Anda menemukan kesulitan atau memiliki pertanyaan, jangan ragu untuk bertanya di kolom komentar!