kavachOS

Last login tracking

The last login module records every successful authentication event per user. You can show users when and how they last signed in on a security page, or use login history to detect unusual activity.

Setup

import { createKavach } from 'kavachos';
import { createLastLoginModule } from 'kavachos/auth/last-login';

const kavach = await createKavach({ /* ... */ });

const loginHistory = createLastLoginModule(
  { maxHistoryPerUser: 20 },
  kavach.db,
);

createLastLoginModule is stateless and safe to call multiple times against the same database instance.

Recording a login

Call recordLogin after any successful authentication:

await loginHistory.recordLogin({
  userId: 'usr_123',
  method: 'magic-link',
  ip: request.headers.get('x-forwarded-for') ?? undefined,
  userAgent: request.headers.get('user-agent') ?? undefined,
});

Older entries beyond maxHistoryPerUser (default: 10) are pruned automatically on every write.

Reading login data

Last login

const result = await loginHistory.getLastLogin('usr_123');

if (result.success && result.data) {
  console.log(result.data.method);    // 'magic-link'
  console.log(result.data.timestamp); // Date
  console.log(result.data.ip);        // string | null
}

Returns null in data when no history exists for the user.

Full history

const result = await loginHistory.getLoginHistory('usr_123', 5);

if (result.success) {
  for (const event of result.data) {
    console.log(event.method, event.timestamp);
  }
}

Events are returned newest first. The optional limit parameter overrides the module's maxHistoryPerUser.

Supported methods

ValueDescription
email-passwordEmail and password sign-in
magic-linkPasswordless email link
email-otpOne-time code via email
passkeyWebAuthn / FIDO2
username-passwordUsername and password
phone-smsSMS one-time code
siweSign-in with Ethereum
device-authOAuth 2.0 device flow
anonymousAnonymous session
api-keyAPI key authentication
oauth:{provider}Any OAuth provider, e.g. oauth:github

Result type

All methods return Result<T> — either { success: true; data: T } or { success: false; error: KavachError }. No exceptions are thrown.

const result = await loginHistory.getLastLogin(userId);

if (!result.success) {
  console.error(result.error.code, result.error.message);
}

IP addresses are stored as-is. Normalise or hash them before passing if your privacy policy requires it.

On this page