kavachOS
AuthenticationAuth methods

Email and password

Register and sign in with email and password. Passwords hashed with argon2id.

The emailPassword() plugin handles user registration, sign-in, password reset, and optional email verification. Passwords are hashed with argon2id using secure defaults — no configuration required.

Setup

Add the plugin

lib/kavach.ts
import { createKavach } from '@kavachos/core';
import { emailPassword } from '@kavachos/core/plugins/email-password';

const kavach = await createKavach({
  database: { provider: 'postgres', url: process.env.DATABASE_URL! },
  secret: process.env.KAVACH_SECRET!,
  baseUrl: 'https://auth.example.com',
  plugins: [
    emailPassword({
      requireEmailVerification: true, // default: false
    }),
  ],
});

Configure email (for verification and reset)

If you enable requireEmailVerification or want password reset, provide an email sender:

emailPassword({
  requireEmailVerification: true,
  sendEmail: async ({ to, subject, html }) => {
    await resend.emails.send({ from: 'auth@example.com', to, subject, html });
  },
}),

Registration

POST /auth/email-password/register

const res = await fetch('/auth/email-password/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com', password: 'correct horse battery' }),
});

On success, the user is created and a session cookie is set. If requireEmailVerification is on, the user gets an email first and cannot sign in until verified.

Sign-in

POST /auth/email-password/login

const res = await fetch('/auth/email-password/login', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com', password: 'correct horse battery' }),
});

Returns { userId, sessionId } on success. The session cookie is HttpOnly and SameSite=Lax by default.

Password reset

POST /auth/email-password/forgot-password

await fetch('/auth/email-password/forgot-password', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com' }),
});

KavachOS sends a signed reset link valid for 1 hour. The response is always 200 to prevent email enumeration.

Submit the new password

POST /auth/email-password/reset-password

await fetch('/auth/email-password/reset-password', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: tokenFromUrl, password: 'new-strong-password' }),
});

Email verification

When requireEmailVerification: true, sign-in returns 403 until the user clicks the link in their email. To resend:

POST /auth/email-password/resend-verification

await fetch('/auth/email-password/resend-verification', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com' }),
});

Options

OptionTypeDefaultDescription
requireEmailVerificationbooleanfalseBlock sign-in until email is verified
passwordMinLengthnumber8Minimum password length
sendEmailfunctionRequired for verification and reset emails
resetTokenTtlnumber3600Reset token lifetime in seconds

argon2id parameters default to OWASP recommended values (memory: 64 MB, iterations: 3, parallelism: 4). Override with argon2Options if your server has different constraints.

On this page