From 938710147a0b09ed3c6f4674ea680ad2ecde4e88 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 1 Oct 2026 09:30:08 -0400 Subject: [PATCH] Delete token --- server/routers/badger/exchangeSession.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/server/routers/badger/exchangeSession.ts b/server/routers/badger/exchangeSession.ts index 31600dc3e..c0c77ed8d 100644 --- a/server/routers/badger/exchangeSession.ts +++ b/server/routers/badger/exchangeSession.ts @@ -4,7 +4,12 @@ import createHttpError from "http-errors"; import { z } from "zod"; import { fromError } from "zod-validation-error"; import logger from "@server/logger"; -import { resourceAccessToken, resources, sessions } from "@server/db"; +import { + resourceAccessToken, + resourceSessions, + resources, + sessions +} from "@server/db"; import { db } from "@server/db"; import { and, eq, inArray, or, sql } from "drizzle-orm"; import { @@ -128,7 +133,18 @@ export async function exchangeSession( ); } - await db.delete(sessions).where(eq(sessions.sessionId, requestToken)); + // Enforce single use: consume the request token. Checking the deleted + // row count makes concurrent exchanges of the same token race safely. + const consumed = await db + .delete(resourceSessions) + .where(eq(resourceSessions.sessionId, requestSession.sessionId)) + .returning(); + + if (consumed.length === 0) { + return next( + createHttpError(HttpCode.UNAUTHORIZED, "Invalid request token") + ); + } const token = generateSessionToken();