Session Management
ISessionStore enables device-aware sessions — letting users see and revoke individual logged-in devices.
Session lifecycle
Interface
import { ISessionStore, SessionInfo } from '@nik2208/node-auth';
export class MySessionStore implements ISessionStore {
async createSession(info: Omit<SessionInfo, 'sessionHandle'>): Promise<SessionInfo> {
const sessionHandle = crypto.randomUUID();
await db('sessions').insert({ sessionHandle, ...info });
return { sessionHandle, ...info };
}
async getSession(sessionHandle: string): Promise<SessionInfo | null> {
return db('sessions').where({ sessionHandle }).first() ?? null;
}
async getSessionsForUser(userId: string): Promise<SessionInfo[]> {
return db('sessions').where({ userId });
}
async updateSessionLastActive(sessionHandle: string): Promise<void> {
await db('sessions').where({ sessionHandle }).update({ lastActiveAt: new Date() });
}
async revokeSession(sessionHandle: string): Promise<void> {
await db('sessions').where({ sessionHandle }).delete();
}
async revokeAllSessionsForUser(userId: string): Promise<void> {
await db('sessions').where({ userId }).delete();
}
async deleteExpiredSessions(): Promise<void> {
await db('sessions').where('expiresAt', '<', new Date()).delete();
}
}
SessionInfo Model
interface SessionInfo {
sessionHandle: string; // Unique opaque identifier
userId: string;
tenantId?: string;
createdAt: Date;
expiresAt: Date;
lastActiveAt?: Date;
userAgent?: string;
ipAddress?: string;
data?: Record<string, unknown>;
}
Usage
app.use('/auth', auth.router({ sessionStore }));
Sessions are automatically created on login and updated on each token refresh. Expired sessions can be purged via:
POST /auth/sessions/cleanup
This endpoint is only mounted when sessionStore is provided and its deleteExpiredSessions method is implemented.
Managing sessions via Admin Panel
The Admin Panel's Sessions tab shows all active sessions and lets you revoke individual ones:
app.use('/admin', createAdminRouter(userStore, {
adminSecret: process.env.ADMIN_SECRET!,
sessionStore,
}));
Or via the Admin REST API directly:
// List all sessions
const sessions = await fetch('/admin/api/sessions', {
headers: { Authorization: `Bearer ${adminSecret}` },
}).then(r => r.json());
// Revoke one session
await fetch(`/admin/api/sessions/${sessionHandle}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${adminSecret}` },
});