Users who cannot see their active sessions cannot detect unauthorized access. If an attacker establishes a session from an unfamiliar IP or device, the account owner has no mechanism to discover it or revoke it — they must wait for the application to enforce concurrent session limits or for a timeout. CWE-613 and OWASP A07 identify session visibility as a component of proper session management. Giving users a self-service session management page transforms passive victims into active defenders: they can see an unexpected location, terminate the session, and change their credentials before the attacker completes a transaction.
Low because the attacker still needs a valid session token to exploit the gap, but the absence of session visibility removes the user's only self-service mechanism for detecting and revoking unauthorized concurrent access.
Add GET and DELETE endpoints in src/app/api/account/sessions/route.ts:
export async function GET(req: Request) {
const user = await getCurrentUser(req);
const sessions = await db.sessions.findMany({
where: { userId: user.id, expiresAt: { gt: new Date() } },
select: { id: true, device: true, location: true,
loginAt: true, lastActivityAt: true }
});
return Response.json(sessions);
}
export async function DELETE(req: Request) {
const { sessionId } = await req.json();
const user = await getCurrentUser(req);
// Verify ownership before terminating
await db.sessions.updateMany({
where: { id: sessionId, userId: user.id },
data: { terminatedAt: new Date() }
});
return Response.json({ ok: true });
}
The session list must show at least: device description, approximate location, login timestamp, and last-activity timestamp. Gate termination on userId ownership to prevent cross-user session deletion.
finserv-session-security.concurrent-control.user-view-terminate-sessionslow"0 active session views — users cannot see or manage their sessions" or "Session list exists but 0 termination endpoints — view-only"src/app/api/account/sessions/route.ts):
// app/api/account/sessions/route.ts
export async function GET(req: Request) {
const user = await getCurrentUser(req);
const sessions = await db.sessions.findMany({
where: { userId: user.id, expiresAt: { gt: new Date() } },
select: { id, device, location, loginAt, lastActivityAt }
});
return Response.json(sessions);
}
export async function DELETE(req: Request) {
const { sessionId } = await req.json();
await db.sessions.update({
where: { id: sessionId },
data: { terminatedAt: new Date() }
});
return Response.json({ ok: true });
}