
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
LightAuth: lightweight authentication library with Arctic OAuth, Argon2id hashing, and Kysely-backed storage
A lightweight authentication library built with Arctic (OAuth 2.0), Argon2id (password hashing), and Mech Storage as the database backend. Designed for teams who need production-ready auth with minimal bundle size (~15KB vs 150KB).
useAuth, AuthProvider)Note: Install from npm as
lightauth.
npm install lightauth arctic kysely @node-rs/argon2 oslo
Or using a specific version/tag:
npm install lightauth arctic kysely @node-rs/argon2 oslo
Or add to package.json:
{
"dependencies": {
"lightauth": "^0.3.0",
"arctic": "^2.0.0",
"kysely": "^0.27.3",
"@node-rs/argon2": "^2.0.0",
"oslo": "^1.2.0"
}
}
Create lib/auth.ts:
import { createMechAuth } from "lightauth"
export const authConfig = createMechAuth({
secret: process.env.AUTH_SECRET!,
baseUrl: process.env.BASE_URL || "http://localhost:3000",
database: {
appId: process.env.MECH_APP_ID!,
apiKey: process.env.MECH_API_KEY!,
},
oauth: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
redirectUri: `${process.env.BASE_URL}/auth/callback/github`,
},
},
})
Create app/api/auth/[...path]/route.ts:
import { handleMechAuthRequest } from "lightauth"
import { authConfig } from "@/lib/auth"
export async function GET(request: Request) {
return handleMechAuthRequest(request, authConfig)
}
export async function POST(request: Request) {
return handleMechAuthRequest(request, authConfig)
}
Create src/auth.ts:
import { createMechAuth, handleMechAuthRequest } from "lightauth"
export function createAuth(env: Env) {
return createMechAuth({
secret: env.AUTH_SECRET,
baseUrl: "https://your-worker.workers.dev",
database: {
appId: env.MECH_APP_ID,
apiKey: env.MECH_API_KEY,
},
isProduction: true,
})
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url)
if (url.pathname.startsWith("/auth")) {
const config = createAuth(env)
return handleMechAuthRequest(request, config)
}
return new Response("Hello World")
}
}
Wrap your app with AuthProvider:
// app/providers.tsx
"use client"
import { AuthProvider } from "lightauth/react"
export function Providers({ children }: { children: React.ReactNode }) {
return (
<AuthProvider baseUrl="/api/auth">
{children}
</AuthProvider>
)
}
Use in components:
"use client"
import { useAuth } from "lightauth/react"
export function LoginButton() {
const { user, loading, signIn, signOut } = useAuth()
if (loading) return <p>Loading...</p>
if (user) {
return (
<div>
<p>Welcome, {user.email}!</p>
<button onClick={signOut}>Sign Out</button>
</div>
)
}
return (
<button onClick={() => signIn("user@example.com", "password")}>
Sign In
</button>
)
}
All configuration must be passed explicitly to createMechAuth():
| Parameter | Type | Required | Description |
|---|---|---|---|
secret | string | Yes | Secret for signing tokens (minimum 32 characters recommended) |
baseUrl | string | Yes | Your application's base URL (e.g., https://example.com) |
database.appId | string | Yes | Your Mech app UUID |
database.apiKey | string | Yes | Your Mech API key |
isProduction | boolean | No | Set to true in production (enables secure cookies) |
| Parameter | Type | Description |
|---|---|---|
oauth | OAuthProvidersConfig | OAuth provider configuration (GitHub, Google) |
session | SessionConfig | Session configuration (expiration, cookie settings) |
password | PasswordConfig | Password validation rules (minLength) |
cors | CorsConfig | CORS configuration for browser clients |
Three session configurations are available:
import {
defaultSessionConfig, // 7 days, sameSite: lax
shortSessionConfig, // 1 hour, sameSite: strict
longSessionConfig // 30 days, sameSite: lax
} from "lightauth"
const config = createMechAuth({
// ...
session: shortSessionConfig, // Use preset
})
Node.js / Next.js (.env.local):
AUTH_SECRET=your-secret-key-at-least-32-chars
BASE_URL=http://localhost:3000
MECH_APP_ID=550e8400-e29b-41d4-a716-446655440000
MECH_API_KEY=your-mech-api-key
# OAuth (optional)
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
Cloudflare Workers (wrangler.toml):
[vars]
BASE_URL = "https://your-worker.workers.dev"
# Use `wrangler secret put` for sensitive values:
# wrangler secret put AUTH_SECRET
# wrangler secret put MECH_API_KEY
# wrangler secret put GITHUB_CLIENT_SECRET
createMechAuth(options)Creates an authentication configuration object.
import { createMechAuth } from "lightauth"
const config = createMechAuth({
secret: process.env.AUTH_SECRET!,
baseUrl: "https://example.com",
database: {
appId: process.env.MECH_APP_ID!,
apiKey: process.env.MECH_API_KEY!,
},
oauth: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
redirectUri: "https://example.com/auth/callback/github",
},
},
session: defaultSessionConfig,
password: { minLength: 12 },
})
Returns: MechAuthConfig - Configuration object to pass to handleMechAuthRequest()
handleMechAuthRequest(request, config)Universal request handler for all authentication routes.
import { handleMechAuthRequest } from "lightauth"
const response = await handleMechAuthRequest(request, authConfig)
Parameters:
request: Request - Web standard Request objectconfig: MechAuthConfig - Configuration from createMechAuth()Returns: Promise<Response> - Web standard Response object
<AuthProvider>Wraps your app to provide authentication context.
import { AuthProvider } from "lightauth/react"
<AuthProvider baseUrl="/api/auth">
{children}
</AuthProvider>
useAuth()Access authentication state and actions.
import { useAuth } from "lightauth/react"
const {
user, // Current user or null
loading, // Loading state
error, // Error message or null
signIn, // (email, password) => Promise<void>
signUp, // (email, password, name?) => Promise<void>
signOut, // () => Promise<void>
loginWithGithub, // () => Promise<void>
loginWithGoogle, // () => Promise<void>
refresh, // () => Promise<void>
} = useAuth()
All routes are handled by handleMechAuthRequest():
| Route | Method | Description |
|---|---|---|
/auth/signup | POST | Email/password signup |
/auth/login | POST | Email/password login |
/auth/logout | POST | Sign out current user |
/auth/session | GET | Get current session |
/auth/verify-email | POST | Request email verification |
/auth/reset-password | POST | Request password reset |
/auth/reset-password/confirm | POST | Confirm password reset with token |
/auth/github | GET | Initiate GitHub OAuth flow |
/auth/callback/github | GET | GitHub OAuth callback |
/auth/google | GET | Initiate Google OAuth flow |
/auth/callback/google | GET | Google OAuth callback |
This architecture means:
Compatible with Cloudflare Workers and Pages when using an HTTP-based database backend. Note that email/password uses @node-rs/argon2 (native) and may require a Node runtime.
process.env usage - All configuration is explicitenv bindings - Pass secrets from environment# Install dependencies
bun install
# Run tests
bun run test
# Run tests in watch mode
bun run test:watch
# Build
bun run build
# Output appears in dist/
If migrating from Better Auth:
better-auth dependency with arctic, @node-rs/argon2, oslocreateMechAuth() - returns MechAuthConfig instead of auth instancehandleMechAuthRequest() instead of auth.handlerbetter-auth/react to lightauth/reactcookie objectSee MIGRATION_GUIDE.md for detailed migration steps.
MIT
FAQs
LightAuth: lightweight authentication library with Arctic OAuth, Argon2id hashing, and Kysely-backed storage
We found that lightauth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.