agentsclimarketplace

Lucia auth

Skill ComeOnOliver/skillshub/skills/TerminalSkills/skills/lucia-auth

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.From the repository description

Install
npx -y skills add ComeOnOliver/skillshub --skill lucia-auth

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

4.9 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it

Lucia Auth β€” Simple Authentication

You are an expert in Lucia, the lightweight authentication library for TypeScript. You help developers implement session-based authentication with email/password, OAuth (Google, GitHub, Discord), magic links, and two-factor authentication β€” providing a simple, database-agnostic auth layer that you understand and control, without the complexity of full auth platforms.

Core Capabilities

Session Management

// lib/auth.ts
import { Lucia } from "lucia";
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
import { db } from "./db";
import { users, sessions } from "./db/schema";

const adapter = new DrizzlePostgreSQLAdapter(db, sessions, users);

export const lucia = new Lucia(adapter, {
  sessionCookie: {
    expires: false,                        // Session cookie (cleared on browser close)
    attributes: { secure: process.env.NODE_ENV === "production" },
  },
  getUserAttributes: (attributes) => ({
    email: attributes.email,
    name: attributes.name,
    avatarUrl: attributes.avatar_url,
  }),
});

// Email/password signup
async function signup(email: string, password: string, name: string) {
  const hashedPassword = await new Argon2id().hash(password);
  const userId = generateIdFromEntropySize(10);

  await db.insert(users).values({
    id: userId,
    email,
    name,
    hashedPassword,
  });

  const session = await lucia.createSession(userId, {});
  const sessionCookie = lucia.createSessionCookie(session.id);
  return sessionCookie;                    // Set as response cookie
}

// Login
async function login(email: string, password: string) {
  const user = await db.query.users.findFirst({ where: eq(users.email, email) });
  if (!user) throw new Error("Invalid credentials");

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

  const session = await lucia.createSession(user.id, {});
  return lucia.createSessionCookie(session.id);
}

// Validate session (middleware)
async function validateRequest(request: Request) {
  const cookieHeader = request.headers.get("Cookie");
  const sessionId = lucia.readSessionCookie(cookieHeader ?? "");
  if (!sessionId) return { user: null, session: null };

  const result = await lucia.validateSession(sessionId);
  return result;                           // { user, session } or { user: null, session: null }
}

// Logout
async function logout(sessionId: string) {
  await lucia.invalidateSession(sessionId);
  return lucia.createBlankSessionCookie();
}

OAuth (Google)

import { Google } from "arctic";

const google = new Google(
  process.env.GOOGLE_CLIENT_ID!,
  process.env.GOOGLE_CLIENT_SECRET!,
  "https://myapp.com/auth/google/callback",
);

// Redirect to Google
app.get("/auth/google", async (c) => {
  const [url, codeVerifier, state] = await google.createAuthorizationURL();
  // Store codeVerifier and state in cookie
  return c.redirect(url.toString());
});

// Handle callback
app.get("/auth/google/callback", async (c) => {
  const { code, state } = c.req.query();
  const tokens = await google.validateAuthorizationCode(code, codeVerifier);
  const googleUser = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
    headers: { Authorization: `Bearer ${tokens.accessToken()}` },
  }).then(r => r.json());

  // Find or create user
  let user = await db.query.users.findFirst({ where: eq(users.email, googleUser.email) });
  if (!user) {
    const userId = generateIdFromEntropySize(10);
    [user] = await db.insert(users).values({
      id: userId, email: googleUser.email, name: googleUser.name, avatar_url: googleUser.picture,
    }).returning();
  }

  const session = await lucia.createSession(user.id, {});
  const cookie = lucia.createSessionCookie(session.id);
  return c.redirect("/dashboard", { headers: { "Set-Cookie": cookie.serialize() } });
});

Installation

npm install lucia arctic                   # Lucia + OAuth helpers
npm install @lucia-auth/adapter-drizzle    # Or adapter-prisma, adapter-mongoose, etc.
npm install @node-rs/argon2                # Password hashing

Best Practices

  1. Session-based β€” Lucia uses server-side sessions + cookies; more secure than JWT for web apps
  2. Database-agnostic β€” Adapters for Drizzle, Prisma, Mongoose, better-sqlite3, Turso, etc.
  3. Arctic for OAuth β€” Use arctic library for OAuth providers; handles PKCE, state, tokens
  4. Argon2 for passwords β€” Use @node-rs/argon2 for hashing; industry standard, timing-safe
  5. Cookie security β€” Set secure: true in production; httpOnly is automatic
  6. Session validation β€” Call validateSession() on every request; auto-extends session expiry
  7. Invalidation β€” invalidateSession for logout; invalidateUserSessions for security reset
  8. No magic β€” Lucia is explicit; you write the signup/login/oauth flows; you understand every line

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.