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
| Value | Description |
|---|---|
email-password | Email and password sign-in |
magic-link | Passwordless email link |
email-otp | One-time code via email |
passkey | WebAuthn / FIDO2 |
username-password | Username and password |
phone-sms | SMS one-time code |
siwe | Sign-in with Ethereum |
device-auth | OAuth 2.0 device flow |
anonymous | Anonymous session |
api-key | API 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.