diff --git a/apps/server/src/auth/github.ts b/apps/server/src/auth/github.ts index 60937e4f..6d551cfa 100644 --- a/apps/server/src/auth/github.ts +++ b/apps/server/src/auth/github.ts @@ -263,10 +263,11 @@ export const cliAuth = (db: Database) => .post( "/exchange", async ({ body, set }) => { + const tokenHash = await hashToken(body.token); const [st] = await db .select() .from(setupTokens) - .where(and(eq(setupTokens.token, body.token), eq(setupTokens.redeemed, false))) + .where(and(eq(setupTokens.token, tokenHash), eq(setupTokens.redeemed, false))) .limit(1); if (!st || st.expiresAt < new Date()) { diff --git a/apps/server/src/user/routes.ts b/apps/server/src/user/routes.ts index b7570f8f..bda0f54e 100644 --- a/apps/server/src/user/routes.ts +++ b/apps/server/src/user/routes.ts @@ -13,6 +13,7 @@ import { sessions, } from "../db/schema"; import { jwtAuth, apiKeyAuth } from "../auth/middleware"; +import { hashToken } from "../auth/tokens"; import { authAudit } from "../auth/audit"; import { matchSessionRepo, normalizeFullName } from "../social/github-sync"; import { __clearClaimCaches } from "./claim"; @@ -71,14 +72,14 @@ export const userRoutes = (db: Database) => { params: t.Object({ id: t.String() }) }, ) - // POST /api/me/setup-token — generate a new setup token .post("/setup-token", async ({ user }) => { const token = crypto.randomUUID(); const expiresAt = new Date(Date.now() + 10 * 60 * 1000); + // Persist the SHA-256 hash; raw token is returned once and never re-read. await db.insert(setupTokens).values({ userId: user.id, - token, + token: await hashToken(token), expiresAt, });