test(sessions): revoke by the public handle, and prove the row id is not a key

This commit is contained in:
Marc-André Bombeck committed 2026-07-19 12:20:25 +02:00
1 parent fd9603a578
commit 4bee263a59
1 file changed
+23 -6
@@ -5,12 +5,17 @@
* Covers the DB-layer contracts the unit mocks can't pin:
* - destroyOtherSessions keeps the current session, deletes the rest, revokes
* native refresh tokens, and leaves API tokens untouched.
* - destroySessionById is scoped to the owning user (no cross-user delete).
* - destroySessionById is scoped to the owning user (no cross-user delete)
* and takes the public handle, never the row id.
* - the (userId, deviceHash) unique index enforces the login-alert dedupe.
*/
import { beforeEach, describe, expect, it } from "vitest";
import { destroyOtherSessions, destroySessionById } from "@/lib/auth/session";
import {
destroyOtherSessions,
destroySessionById,
sessionHandle,
} from "@/lib/auth/session";
import { getPrismaClient, truncateAllTables } from "./setup";
beforeEach(async () => {
@@ -85,14 +90,26 @@ describe("destroySessionById", () => {
data: { userId: other.id, expiresAt: new Date(Date.now() + 1e6) },
});
// Cross-user attempt: owner tries to delete the intruder's session.
expect(await destroySessionById(owner.id, otherSession.id)).toBe(false);
// Cross-user attempt: owner presents the intruder's handle.
expect(
await destroySessionById(owner.id, sessionHandle(otherSession.id)),
).toBe(false);
expect(
await prisma.session.findUnique({ where: { id: otherSession.id } }),
).not.toBeNull();
// Owned delete succeeds.
expect(await destroySessionById(owner.id, ownerSession.id)).toBe(true);
// The row id is not an accepted key: a caller who somehow learned it
// still cannot revoke with it, which is what keeps the id out of the
// client's hands from being load-bearing in both directions.
expect(await destroySessionById(owner.id, ownerSession.id)).toBe(false);
expect(
await prisma.session.findUnique({ where: { id: ownerSession.id } }),
).not.toBeNull();
// Owned delete succeeds on the handle.
expect(
await destroySessionById(owner.id, sessionHandle(ownerSession.id)),
).toBe(true);
expect(
await prisma.session.findUnique({ where: { id: ownerSession.id } }),
).toBeNull();