Skip to content
Back to skills

Lucia

ASecurity

> Lightweight session-based auth library — adapter pattern, no JWT, full control over your auth flow.

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 26, 2026
databasestypescriptgosqlnodegitapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 26, 2026

npx -y skills add nhan03bit/ultrathink --skill lucia --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Lucia?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Lucia
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nhan03bit-lucia/badge)](https://www.skillsdirectory.com/skills/nhan03bit-lucia)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Lucia

> Lightweight session-based auth library — adapter pattern, no JWT, full control over your auth flow.

## When to Use
- Building auth from scratch with full control (not drop-in UI)
- Need session-based auth with database-backed sessions
- Using Drizzle, Prisma, or other ORMs (adapter pattern)
- Integrating OAuth via Arctic library
- Want type-safe sessions with custom user attributes

## Core Patterns

### Setup with Drizzle Adapter
```typescript
// lib/auth.ts
import { Lucia } from "lucia";
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
import { db, sessionTable, userTable } from "./db";

const adapter = new DrizzlePostgreSQLAdapter(db, sessionTable, userTable);

export const lucia = new Lucia(adapter, {
  sessionCookie: { attributes: { secure: process.env.NODE_ENV === "production" } },
  getUserAttributes: (attrs) => ({ email: attrs.email, name: attrs.name }),
});

declare module "lucia" {
  interface Register { Lucia: typeof lucia; DatabaseUserAttributes: { email: string; name: string } }
}
```

### Session Management
```typescript
import { lucia } from "@/lib/auth";
import { generateIdFromEntropySize } from "lucia";

// Create session after login
const session = await lucia.createSession(userId, {});
const cookie = lucia.createSessionCookie(session.id);
cookies().set(cookie.name, cookie.value, cookie.attributes);

// Validate session (middleware / server component)
const cookieValue = cookies().get(lucia.sessionCookieName)?.value ?? "";
const { session, user } = await lucia.validateSession(cookieValue);
if (session?.fresh) {
  const fresh = lucia.createSessionCookie(session.id);
  cookies().set(fresh.name, fresh.value, fresh.attributes);
}

// Logout
await lucia.invalidateSession(sessionId);
const blank = lucia.createBlankSessionCookie();
cookies().set(blank.name, blank.value, blank.attributes);
```

### Password Auth (Argon2)
```typescript
import { hash, verify } from "@node-rs/argon2";

// Sign up
const hashedPassword = await hash(password, { memoryCost: 19456, timeCost: 2, parallelism: 1 });
const userId = generateIdFromEntropySize(10);
await db.insert(userTable).values({ id: userId, email, hashedPassword });

// Sign in
const valid = await verify(user.hashedPassword, password);
if (!valid) throw new Error("Invalid credentials");
```

### OAuth with Arctic
```typescript
import { GitHub } from "arctic";

export const github = new GitHub(clientId, clientSecret, redirectURI);

// Redirect to provider
const state = generateState();
const url = github.createAuthorizationURL(state, ["user:email"]);
cookies().set("oauth_state", state, { httpOnly: true, maxAge: 600 });

// Callback — exchange code for tokens, then create session
const tokens = await github.validateAuthorizationCode(code);
const githubUser = await fetch("https://api.github.com/user", {
  headers: { Authorization: `Bearer ${tokens.accessToken()}` },
}).then((r) => r.json());
```

## Key Features
- **Adapters**: Drizzle, Prisma, Mongoose, better-sqlite3, unstorage — swap DB without changing auth logic
- **Framework helpers**: `astro`, `next`, `sveltekit` middleware examples in docs — no lock-in
- **Type-safe sessions**: Extend `DatabaseUserAttributes` for fully typed `user` on every request
- **Cookie control**: `sessionCookie.attributes` — set `secure`, `sameSite`, `domain`, `maxAge`
- **Session table**: Requires `id` (text PK), `user_id` (FK), `expires_at` (timestamp) columns
- **No JWT**: Sessions live in your DB — revoke instantly, no token expiry lag
- **Arctic OAuth**: 50+ providers (GitHub, Google, Discord, Apple, etc.) via `arctic` package

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.