ideal-auth
raw JSON → 1.2.0 verified Sat Apr 25 auth: no javascript
Auth primitives for the JS ecosystem — stateless encrypted sessions, password hashing, and two-factor support. Zero framework dependencies; inspired by Laravel's Auth and Hash facades. Current stable version is 1.2.0, released monthly. Key differentiators: uses iron-session for AES-256-CBC + HMAC encrypted cookies, supports two session modes (resolveUser for DB-backed, sessionFields for zero DB calls), built-in TOTP for 2FA, and per-request autoTouch override for frameworks like Next.js. Ships TypeScript types, requires Node >=18, and has optional bcryptjs peer dependency.
Common errors
error Error: Secret must be at least 32 characters long ↓
cause IDEAL_AUTH_SECRET is too short in environment variables.
fix
Generate a 32+ character secret: bunx ideal-auth secret, then add to .env.
error Cannot find module 'bcryptjs' ↓
cause bcryptjs not installed but createHash() is used.
fix
Run: npm install bcryptjs or provide a custom HashInstance.
error Type 'undefined' is not assignable to type 'string' ↓
cause sessionFields array not declared with 'as const' causing TypeScript to infer string[].
fix
Add 'as const' to the sessionFields array: const sessionFields = ['email', 'name'] as const;
error Type 'typeof auth' is not a valid async function ↓
cause Attempting to call auth() without awaiting in an async context incorrectly.
fix
Ensure auth() is called with await: const session = await auth();
error Error: iron-session cookie parsing failed ↓
cause Corrupted session cookie or mismatched secret.
fix
Regenerate IDEAL_AUTH_SECRET and clear all session cookies.
Warnings
breaking v1.0.0: createAuth now requires a single type parameter TUser; removed previous dual-generic signature. ↓
fix Update to createAuth<SessionUser>({ ... }) — remove the second type argument.
breaking v0.7.0: Simplified type system — createAuth takes only TUser, not TFields. ↓
fix Migrate to single generic: createAuth<SessionUser>({ ... }).
deprecated v0.5.0: Session secret environment variable renamed from IDEAL_AUTH_SESSION_SECRET to IDEAL_AUTH_SECRET. ↓
fix Rename environment variable to IDEAL_AUTH_SECRET.
gotcha Per-request autoTouch override is only available in v1.2.0+; earlier versions ignore per-request options. ↓
fix Upgrade to v1.2.0 or later to use auth({ autoTouch: true }).
gotcha bcryptjs is optional but createHash() fails at runtime if not installed; no clear error message. ↓
fix Install bcryptjs as a dependency if using createHash() or provide a custom HashInstance.
gotcha sessionFields must be declared with 'as const' to get narrow types; otherwise user() returns generic type. ↓
fix Use 'as const' when defining sessionFields array.
gotcha secret must be at least 32 characters; shorter values throw an error at runtime. ↓
fix Generate a 32+ character secret via 'bunx ideal-auth secret'.
Install
npm install ideal-auth yarn add ideal-auth pnpm add ideal-auth Imports
- createAuth wrong
import createAuth from 'ideal-auth'correctimport { createAuth } from 'ideal-auth' - createHash
import { createHash } from 'ideal-auth' - prehash
import { prehash } from 'ideal-auth'
Quickstart
import { createAuth, createHash } from 'ideal-auth';
import { cookies } from 'next/headers';
import { db } from '@/lib/db';
const hash = createHash({ rounds: 12 });
export const auth = createAuth({
secret: process.env.IDEAL_AUTH_SECRET ?? '',
cookie: {
get: async (name) => (await cookies()).get(name)?.value,
set: async (name, value, opts) => (await cookies()).set(name, value, opts),
delete: async (name) => (await cookies()).delete(name),
},
hash,
resolveUser: async (id) => db.user.findUnique({ where: { id } }),
resolveUserByCredentials: async (creds) => db.user.findUnique({ where: { email: creds.email } }),
});
// In a server action:
const session = auth();
await session.attempt({ email: 'user@example.com', password: 's3cret' });
const user = await session.user();
await session.logout();