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
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
Request a reset link
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
| Option | Type | Default | Description |
|---|---|---|---|
requireEmailVerification | boolean | false | Block sign-in until email is verified |
passwordMinLength | number | 8 | Minimum password length |
sendEmail | function | — | Required for verification and reset emails |
resetTokenTtl | number | 3600 | Reset 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.