Cara Menggunakan Auth API Terbaik untuk Autentikasi Modern

Ashley Goolam

Ashley Goolam

14 November 2025

Cara Menggunakan Auth API Terbaik untuk Autentikasi Modern

Otentikasi adalah landasan setiap aplikasi web modern, namun pengaturannya tetap menjadi salah satu tantangan paling memakan waktu yang dihadapi pengembang. Hadir Better Auth API—solusi otentikasi agnostik-framework yang menjanjikan untuk mengubah cara kita mengimplementasikan manajemen pengguna. Dalam panduan komprehensif ini, kita akan membahas pembangunan aplikasi full-stack lengkap yang menunjukkan kekuatan dan kesederhanaan Better Auth, menggunakan Bun untuk kinerja yang sangat cepat.

💡
Menginginkan alat Pengujian API hebat yang menghasilkan Dokumentasi API yang indah?

Menginginkan platform All-in-One terintegrasi untuk Tim Pengembang Anda agar dapat bekerja sama dengan produktivitas maksimum?

Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
tombol

Apa itu Better Auth API?

Better Auth API adalah kerangka kerja otentikasi modern, sumber terbuka, yang dirancang untuk bekerja dengan mulus di setiap lingkungan JavaScript. Berbeda dengan pustaka otentikasi tradisional yang mengunci Anda ke ekosistem tertentu, Better Auth menyediakan API terpadu yang beradaptasi dengan tumpukan teknologi Anda—baik Anda menggunakan React, Vue, Svelte, atau vanilla JavaScript di frontend, dan Node.js, Bun, atau Deno di backend. Arsitektur berbasis plugin-nya mendukung berbagai strategi otentikasi, mulai dari email/kata sandi tradisional hingga penyedia OAuth, passkey, dan magic link, semuanya sambil mempertahankan keamanan tipe dan pengalaman pengembang yang sangat baik.

otentikasi yang lebih baik

Memulai dengan Better Auth: Prasyarat dan Penyiapan Proyek

Sebelum menyelami kode, pastikan Anda telah menginstal hal-hal berikut:

ide vs code

Meskipun penyiapan ini berfungsi sempurna dengan npm, kami akan mendemonstrasikan alur kerja Bun, yang menawarkan instalasi paket 3-5 kali lebih cepat dan pengalaman pengembangan yang lebih efisien.

Membangun Proyek Contoh: Implementasi Langkah demi Langkah

Mari kita buat sistem otentikasi praktis dengan frontend React dan backend Express, lengkap dengan persistensi basis data.

Langkah 1: Penyiapan Backend dengan Express dan Drizzle ORM

1. Inisialisasi Proyek Backend

Pertama, buat dan masuk ke direktori backend Anda:

mkdir better-auth-backend
cd better-auth-backend
bun init -y

2. Instal Dependensi

Kita akan membutuhkan Express untuk server, Better Auth untuk otentikasi, dan Drizzle ORM untuk manajemen basis data:

bun add express better-auth drizzle-orm
bun add -D @types/bun @types/express drizzle-kit

3. Konfigurasi Variabel Lingkungan

Buat file .env untuk menyimpan konfigurasi sensitif:

BETTER_AUTH_SECRET=your-secret-key-here # Generate with: openssl rand -base64 32
BETTER_AUTH_URL=http://localhost:3000
DATABASE_URL=local.db

BETTER_AUTH_SECRET juga dapat dibuat di situs web better-auth.

4. Buat Skema Basis Data dengan Drizzle ORM

Better Auth bekerja paling baik dengan Drizzle, yang menyediakan dukungan TypeScript yang sangat baik dan menghindari masalah modul native. Buat src/db/schema.ts:

import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";

export const user = sqliteTable("user", {
  id: text("id").primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  emailVerified: integer('email_verified', { mode: 'boolean' }).notNull().default(false),
  image: text('image'),
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
  updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
});

export const session = sqliteTable("session", {
  id: text("id").primaryKey(),
  expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull(),
  token: text('token').notNull().unique(),
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
  userId: text('user_id').notNull(),
});

export const account = sqliteTable("account", {
  id: text("id").primaryKey(),
  accountId: text('account_id').notNull(),
  providerId: text('provider_id').notNull(),
  userId: text('user_id').notNull(),
  accessToken: text('access_token'),
  refreshToken: text('refresh_token'),
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
});

export const verification = sqliteTable("verification", {
  id: text("id").primaryKey(),
  identifier: text('identifier').notNull(),
  value: text('value').notNull(),
  expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull(),
});

5. Konfigurasi Koneksi Basis Data

Buat src/db/index.ts menggunakan binding SQLite native Bun:

import { Database } from "bun:sqlite";
import { drizzle } from "drizzle-orm/bun-sqlite";

const sqlite = new Database("local.db");
export const db = drizzle(sqlite);

6. Siapkan Konfigurasi Better Auth

Buat src/lib/auth.ts untuk mengonfigurasi Better Auth API:

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "../db";
import { user, session, account, verification } from "../db/schema";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "sqlite",
    schema: {
      user: user,
      session: session,
      account: account,
      verification: verification,
    },
  }),
  emailAndPassword: {
    enabled: true,
  },
  trustedOrigins: ["http://localhost:5173"],
});

7. Buat Server Express

Di src/index.ts, pasang handler Better Auth API:

import express from "express";
import cors from "cors";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./lib/auth";

const app = express();
const PORT = process.env.PORT || 3000;

app.use(
  cors({
    origin: "http://localhost:5173",
    credentials: true,
  })
);

// Mount Better Auth API at /api/auth
app.use("/api/auth", toNodeHandler(auth));
app.use(express.json());

app.get("/api/me", async (req, res) => {
  const session = await auth.api.getSession({
    headers: req.headers,
  });
  
  if (!session) {
    return res.status(401).json({ error: "Unauthorized" });
  }
  
  res.json({ user: session.user });
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

8. Jalankan Migrasi Basis Data

Buat drizzle.config.ts di root backend:

import { defineConfig } from "drizzle-kit";

export default defineConfig({
  dialect: "sqlite",
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dbCredentials: {
    url: "local.db",
  },
});

Jalankan migrasi untuk membuat tabel:

bunx drizzle-kit push
struktur proyek server backend

Langkah 2: Penyiapan Frontend dengan React dan Vite

1. Buat Aplikasi React

Di terminal baru, inisialisasi frontend:

bun create vite better-auth-frontend --template react-ts
cd better-auth-frontend

2. Instal Dependensi

bun add better-auth

3. Konfigurasi Tailwind CSS (Pembaruan V4)

Pasca-Tailwind CSS v4 memerlukan penyiapan yang berbeda. Instal paket-paket baru:

bun add -D tailwindcss postcss @tailwindcss/postcss

Buat tailwind.config.js di root proyek:

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Buat postcss.config.js:

export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
}

Buat src/index.css:

@import "tailwindcss";

body {
  margin: 0;
  font-family: system-ui, -apple-system, sans-serif;
}

4. Siapkan Klien Better Auth

Buat src/lib/auth-client.ts:

import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
  baseURL: "http://localhost:3000",
});

export const { signIn, signUp, useSession } = authClient;

5. Bangun UI Otentikasi

Ganti src/App.tsx dengan antarmuka otentikasi lengkap:

import { useState } from 'react';
import { useSession, signIn, signUp } from './lib/auth-client';

function App() {
  const { data: session, isPending } = useSession();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [name, setName] = useState('');

  const handleSignUp = async (e: React.FormEvent) => {
    e.preventDefault();
    await signUp.email({
      name,
      email,
      password,
      callbackURL: '/',
    });
  };

  const handleSignIn = async (e: React.FormEvent) => {
    e.preventDefault();
    await signIn.email({
      email,
      password,
    });
  };

  const handleSignOut = async () => {
    await authClient.signOut();
  };

  if (isPending) return <div className="flex items-center justify-center min-h-screen">Memuat...</div>;

  return (
    <div className="min-h-screen bg-gray-100 flex items-center justify-center p-4">
      <div className="max-w-md w-full bg-white rounded-lg shadow-md p-6">
        <h1 className="text-2xl font-bold text-center mb-6 text-gray-800">
          Uji Better Auth API
        </h1>

        {session?.user ? (
          <div className="space-y-4">
            <div className="bg-green-50 p-4 rounded-md">
              <p className="text-green-800 font-semibold">Masuk sebagai:</p>
              <p className="text-green-700">{session.user.email}</p>
              <p className="text-green-600 text-sm">{session.user.name}</p>
            </div>
            <button
              onClick={handleSignOut}
              className="w-full bg-red-500 hover:bg-red-600 text-white font-medium py-2 px-4 rounded-md transition"
            >
              Keluar
            </button>
          </div>
        ) : (
          <div className="space-y-4">
            <form onSubmit={handleSignUp} className="space-y-3">
              <h2 className="text-lg font-semibold text-gray-700">Daftar</h2>
              <input
                type="text"
                placeholder="Nama"
                value={name}
                onChange={(e) => setName(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
              <input
                type="email"
                placeholder="Email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
              <input
                type="password"
                placeholder="Kata Sandi"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
              <button
                type="submit"
                className="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 rounded-md transition"
              >
                Buat Akun
              </button>
            </form>

            <form onSubmit={handleSignIn} className="space-y-3">
              <h2 className="text-lg font-semibold text-gray-700">Masuk</h2>
              <input
                type="email"
                placeholder="Email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
              <input
                type="password"
                placeholder="Kata Sandi"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                required
              />
              <button
                type="submit"
                className="w-full bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-md transition"
              >
                Masuk
              </button>
            </form>
          </div>
        )}
      </div>
    </div>
  );
}

export default App;
struktur proyek aplikasi frontend

Langkah 3: Menguji Integrasi

1. Mulai Server Backend

cd better-auth-backend
bun dev
jalankan server backend better auth

2. Mulai Pengembangan Frontend

cd better-auth-frontend
bun dev
jalankan aplikasi frontend better auth

3. Uji Alur Otentikasi

daftar atau masuk
Informasi Benar
percobaan masuk dengan informasi salah
Informasi Salah
keluar

Manfaat Utama Better Auth API

Better Auth API membedakan dirinya melalui beberapa keunggulan menarik:

Pertanyaan yang Sering Diajukan

Q1: Bisakah saya menggunakan Better Auth API dengan npm alih-alih Bun?
Jawab: Tentu saja. Meskipun panduan ini menggunakan Bun untuk keuntungan kinerjanya, setiap perintah memiliki padanan npm. Ganti bun add dengan npm install, bun dev dengan npm run dev, dan bunx dengan npx. Satu-satunya kode khusus Bun adalah impor bun:sqlite, yang dapat diganti dengan better-sqlite3 untuk lingkungan Node.js.

Q2: Mengapa kita membutuhkan Drizzle ORM? Tidakkah Better Auth bisa membuat tabel secara otomatis?
Jawab: Better Auth mengikuti prinsip manajemen basis data eksplisit. Drizzle menyediakan migrasi yang aman tipe, versi skema, dan mencegah kehilangan data yang tidak disengaja. Perintah drizzle-kit push adalah penyiapan satu kali yang memberi Anda kontrol penuh atas evolusi basis data Anda.

Q3: Bagaimana jika saya mengalami kesalahan "Missing parameter name"?
Jawab: Ini terjadi saat menggunakan app.all() dengan wildcard di Express. Solusinya adalah menggunakan app.use("/api/auth", toNodeHandler(auth)) sebagai gantinya. Handler Better Auth mengelola semua sub-rute secara internal, sehingga Express tidak memerlukan pencocokan wildcard.

Q4: Bagaimana cara menambahkan penyedia otentikasi sosial?
Jawab: Aktifkan plugin OAuth di konfigurasi Better Auth Anda. Misalnya, untuk menambahkan GitHub:

import { betterAuth } from "better-auth";
import { github } from "better-auth/plugins";

export const auth = betterAuth({
  plugins: [
    github({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    })
  ]
});

Q5: Apakah Better Auth API siap produksi?
Jawab: Ya. Better Auth mendukung otentikasi untuk beberapa produk SaaS dengan ribuan pengguna. Kerangka kerja ini mengimplementasikan manajemen sesi yang aman, perlindungan CSRF, dan mengikuti panduan OWASP. Namun, selalu audit implementasi spesifik Anda dan jaga agar dependensi tetap diperbarui.

Kesimpulan

Membangun otentikasi dari awal tidak lagi diperlukan dengan solusi modern seperti Better Auth API. Dalam panduan ini, kami telah membuat sistem otentikasi lengkap—mulai dari skema basis data hingga komponen UI—dalam beberapa menit! Kombinasi fleksibilitas Better Auth, keamanan tipe Drizzle ORM, dan kinerja Bun menciptakan pengalaman pengembang yang dapat diskalakan dari prototipe hingga produksi.

Proses langkah demi langkah ini menunjukkan bahwa otentikasi, meskipun penting, tidak perlu rumit. Dengan memanfaatkan arsitektur plugin Better Auth dan desain agnostik-framework, Anda dapat fokus membangun fitur-fitur yang penting bagi pengguna Anda daripada bergulat dengan implementasi keamanan.

Baik Anda membangun proyek sampingan atau aplikasi perusahaan, Better Auth API menyediakan fondasi untuk otentikasi yang aman, terukur, dan beradaptasi dengan kebutuhan Anda—bukan sebaliknya.

💡
Menginginkan alat Pengujian API hebat yang menghasilkan Dokumentasi API yang indah?

Menginginkan platform All-in-One terintegrasi untuk Tim Pengembang Anda agar dapat bekerja sama dengan produktivitas maksimum?

Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
tombol

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.