kavachOS
Authentication

Anonymous auth

Let users start immediately as guests and convert to real accounts later.

The anonymousAuth plugin creates a lightweight guest identity on demand. The guest gets a real session and can use your app fully. When they decide to register, their data migrates to the new account without any loss.

Setup

lib/kavach.ts
import { createKavach } from 'kavachos';
import { anonymousAuth } from 'kavachos/plugins/anonymous-auth'; 

const kavach = await createKavach({
  database: { provider: 'postgres', url: process.env.DATABASE_URL! },
  secret: process.env.KAVACH_SECRET!,
  baseUrl: 'https://auth.example.com',
  plugins: [
    anonymousAuth({ 
      guestExpiry: 7 * 24 * 60 * 60, // 7 days in seconds
    }), 
  ],
});

Create guest

POST /auth/anonymous

Creates a new anonymous user and returns a session. No request body needed.

Create guest (client)
const res = await fetch('/auth/anonymous', {
  method: 'POST',
  credentials: 'include',
});

const { user, session } = await res.json();
// user.isAnonymous === true
// user.id is a real user ID — safe to reference in your DB

The response shape is the same as any other sign-in. user.isAnonymous is true and the email and name fields are null.

Upgrade to real account

POST /auth/anonymous/upgrade

Requires an active anonymous session. Converts the guest to a permanent user. The session stays active — the user ID does not change.

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

const { user } = await res.json();
// user.isAnonymous === false

After upgrade, user.isAnonymous becomes false and the account is treated the same as one registered normally. If emailPassword is also active, the email-verification flow applies.

Error codes

CodeStatusMeaning
EMAIL_TAKEN409Email already registered to another account
NOT_ANONYMOUS400The session belongs to a non-guest user

Guest cleanup

Expired anonymous accounts can accumulate. Schedule regular cleanup with the built-in helper:

Scheduled cleanup
import { cleanupAnonymousUsers } from 'kavachos/plugins/anonymous-auth';

// Run daily via cron, queue worker, etc.
await cleanupAnonymousUsers(kavach, {
  olderThan: 7 * 24 * 60 * 60, // delete guests inactive for 7+ days
  dryRun: false,
});

Deleting anonymous users is permanent. Any app data tied to their user ID will become orphaned unless you cascade deletes in your schema or handle cleanup in the onBeforeDelete hook.

Configuration reference

Prop

Type

On this page