Lucia Auth: Otentikasi Modern untuk TypeScript, Bun, dan Hono

I am an enthusiastic researcher and developer with a passion for using technology to innovate in business and education.
Otentikasi (authentication) adalah jantung keamanan sebuah aplikasi.
Namun, membuat sistem login dari nol sering kali merepotkan:
Harus mengelola hash password (bcrypt, argon2)
Membuat sesi aman (cookies, JWT, CSRF)
Mengatur login dengan provider OAuth (Google, GitHub, dst)
Menulis middleware untuk memeriksa user login
Menjamin semua berjalan aman di berbagai platform (Node.js, Edge, Bun)
Nah, Lucia Auth hadir untuk menjawab semua itu dengan prinsip:
โA simple and type-safe authentication library for the modern web.โ
โ๏ธ Apa Itu Lucia?
Lucia adalah library otentikasi open-source berbasis TypeScript yang:
Ringan dan modular (tidak seperti NextAuth yang besar dan opiniated)
Mendukung berbagai runtime: Node.js, Bun, Deno, Cloudflare Workers
Tidak bergantung framework (bisa dipakai di Hono, Elysia, Next.js, SvelteKit, dll)
Memiliki integrasi database yang luas (Prisma, Drizzle, LibSQL, PlanetScale, dsb)
Fokus pada type safety, clean code, dan keamanan modern
Lucia bertujuan agar kamu bisa membuat login, register, dan session management dengan kontrol penuh, tapi tanpa boilerplate.
๐งฉ Arsitektur Dasar Lucia
Secara garis besar, Lucia bekerja dengan tiga komponen utama:
User โ data pengguna yang disimpan di database.
Session โ identitas sementara pengguna yang sedang login.
Adapter โ jembatan antara Lucia dan database (Prisma, Drizzle, dsb).
Client โ Server (Lucia) โ Database (Drizzle/Prisma)
๐ Instalasi
Contoh setup dengan Node.js / Bun dan Drizzle ORM:
npm install lucia @lucia-auth/adapter-drizzle drizzle-orm
๐งฑ Setup Dasar Lucia
Buat file auth.ts:
import { Lucia } from "lucia";
import { DrizzleAdapter } from "@lucia-auth/adapter-drizzle";
import { db } from "./db";
import { sessionTable, userTable } from "./schema";
export const lucia = new Lucia(new DrizzleAdapter(db, sessionTable, userTable), {
sessionCookie: {
name: "session",
attributes: {
secure: process.env.NODE_ENV === "production"
}
},
getUserAttributes: (data) => ({
username: data.username
})
});
export type Auth = typeof lucia;
Penjelasan:
DrizzleAdaptermenyambungkan Lucia ke databasesessionCookiemengatur nama cookie dan keamanannyagetUserAttributesmenentukan data yang akan diakses diuser
๐งฐ Skema Database
Contoh skema Drizzle:
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
export const userTable = pgTable("user", {
id: text("id").primaryKey(),
username: text("username").notNull(),
hashed_password: text("hashed_password").notNull(),
});
export const sessionTable = pgTable("session", {
id: text("id").primaryKey(),
user_id: text("user_id")
.notNull()
.references(() => userTable.id),
expires_at: timestamp("expires_at", { withTimezone: true }).notNull(),
});
๐ Register (Sign Up)
import { lucia } from "./auth";
import { generateId } from "lucia";
import { Argon2id } from "oslo/password";
const passwordHasher = new Argon2id();
export async function register(username: string, password: string) {
const userId = generateId(15);
const hashedPassword = await passwordHasher.hash(password);
await db.insert(userTable).values({
id: userId,
username,
hashed_password: hashedPassword
});
const session = await lucia.createSession(userId, {});
const sessionCookie = lucia.createSessionCookie(session.id);
return { sessionCookie };
}
Lucia memakai library Oslo (resmi dari Lucia) untuk hashing password dengan standar tinggi seperti Argon2id โ aman dan cepat.
๐ Login (Sign In)
export async function login(username: string, password: string) {
const existingUser = await db.query.userTable.findFirst({
where: (u, { eq }) => eq(u.username, username)
});
if (!existingUser) throw new Error("User not found");
const valid = await passwordHasher.verify(
existingUser.hashed_password,
password
);
if (!valid) throw new Error("Invalid password");
const session = await lucia.createSession(existingUser.id, {});
const sessionCookie = lucia.createSessionCookie(session.id);
return { sessionCookie };
}
๐งพ Middleware: Memeriksa User yang Login
Lucia menyediakan cara mudah untuk memvalidasi session dari request:
import { lucia } from "./auth";
export async function getUserFromRequest(request: Request) {
const session = await lucia.validateRequest(request);
if (!session) return null;
return session.user;
}
Kamu bisa gunakan fungsi ini di middleware Hono atau Next.js API Route untuk melindungi route privat.
๐ง Integrasi dengan Hono
Contoh route login sederhana:
import { Hono } from "hono";
import { login, register } from "./auth-controller";
import { lucia } from "./auth";
const app = new Hono();
app.post("/login", async (c) => {
const { username, password } = await c.req.json();
const { sessionCookie } = await login(username, password);
c.header("Set-Cookie", sessionCookie.serialize());
return c.json({ success: true });
});
app.get("/me", async (c) => {
const auth = await lucia.validateRequest(c.req);
if (!auth) return c.json({ user: null });
return c.json({ user: auth.user });
});
๐ Login dengan Google atau GitHub (OAuth)
Lucia menyediakan package resmi untuk OAuth:
npm install @lucia-auth/oauth
Contoh integrasi Google:
import { google } from "@lucia-auth/oauth/providers";
import { lucia } from "./auth";
export const googleAuth = google(lucia, {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectUri: "https://example.com/api/callback/google"
});
Saat user login lewat Google:
Arahkan ke
googleAuth.getAuthorizationUrl()Setelah redirect, tangkap
codedan panggilgoogleAuth.validateCallback(code)Lucia akan otomatis membuat atau menemukan user di database
๐ Keamanan Lucia
Lucia dibangun dengan prinsip keamanan tinggi:
Menggunakan cookie-based session, bukan JWT (lebih aman untuk web)
Tidak menyimpan token rahasia di localStorage
Sesi otomatis kadaluarsa dan dapat diperbarui
Password hashing menggunakan Argon2id (via Oslo)
Type-safe di seluruh proses
โก Dibandingkan Library Lain
| Fitur | Lucia | NextAuth.js | Passport.js |
| Framework agnostic | โ Ya | โ Khusus Next.js | โ ๏ธ Untuk Express |
| Type safety | โ Kuat (Zod + TS) | โ ๏ธ Terbatas | โ Tidak ada |
| OAuth (Google, GitHub, dst) | โ Mudah | โ Banyak provider | โ Banyak provider |
| Session cookie | โ Built-in | โ | โ ๏ธ Bergantung plugin |
| Database bebas | โ (Drizzle, Prisma, SQL, dll) | โ ๏ธ Perlu adapter khusus | โ ๏ธ Manual |
| Runtime | Node.js, Bun, Deno, Cloudflare | Hanya Node.js | Hanya Node.js |
| Ukuran & kontrol | Ringan, fleksibel | Besar, opiniated | Berat & legacy |
๐งฉ Ekosistem Pendukung
๐ง Oslo โ library resmi untuk hashing & crypto
๐งฐ @lucia-auth/adapter-* โ integrasi dengan ORM/DB populer
๐ @lucia-auth/oauth โ provider login sosial
๐ฆ tRPC / Hono / Elysia โ backend framework yang cocok
๐งพ Kesimpulan
Lucia menawarkan keseimbangan sempurna antara kemudahan, fleksibilitas, dan keamanan.
Jika kamu ingin sistem auth yang:
Clean, type-safe, dan tidak bergantung framework
Cocok untuk Bun, Hono, atau Edge Function
Mendukung OAuth tanpa ribet
Bisa diatur penuh sesuai kebutuhan
โฆ maka Lucia adalah pilihan terbaik di ekosistem TypeScript modern.
๐ Rangkuman Cepat
| Aspek | Deskripsi |
| Nama | Lucia Auth |
| Bahasa | TypeScript |
| Arsitektur | Session-based (bukan JWT) |
| ORM Support | Drizzle, Prisma, LibSQL, PlanetScale, dkk |
| OAuth | Google, GitHub, Discord, Facebook, dkk |
| Keamanan | Argon2id, Cookie Secure, HttpOnly |
| Runtime | Node.js, Bun, Deno, Cloudflare |
| Filosofi | Simple. Type-safe. Framework-agnostic. |





