fix: evita logout al cambiar de tenant (race condition refresh token)

This commit is contained in:
Horux Dev
2026-06-22 21:47:13 +00:00
parent 3c7758a599
commit cc002adbd2
4 changed files with 80 additions and 26 deletions

View File

@@ -590,18 +590,6 @@ export async function switchTenant(params: {
throw new AppError(404, 'Empresa no encontrada o desactivada');
}
// Persiste el target como "último tenant activo" — al re-loguear caerá aquí
// sin tener que volver a hacer switch.
const previousTenantId = user.lastTenantId;
await prisma.user.update({
where: { id: user.id },
data: { lastTenantId: targetTenant.id },
});
// Invalida el refresh token actual (puede no existir si el caller pasó el
// access token por error — deleteMany es idempotente).
await prisma.refreshToken.deleteMany({ where: { token: params.currentRefreshToken } });
const [platformRoles, tenants] = await Promise.all([
getPlatformRoles(user.id),
getUserTenants(user.id),
@@ -619,13 +607,26 @@ export async function switchTenant(params: {
const accessToken = generateAccessToken(tokenPayload);
const refreshToken = generateRefreshToken(tokenPayload);
await prisma.refreshToken.create({
data: {
userId: user.id,
token: refreshToken,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
},
});
// Persiste el target como "último tenant activo" y atomiza la rotacion del
// refresh token (delete + create) para evitar race conditions con requests
// concurrentes que intenten refrescar con el token anterior.
const previousTenantId = user.lastTenantId;
await prisma.$transaction([
prisma.user.update({
where: { id: user.id },
data: { lastTenantId: targetTenant.id },
}),
// Invalida el refresh token actual (puede no existir si el caller pasó el
// access token por error — deleteMany es idempotente).
prisma.refreshToken.deleteMany({ where: { token: params.currentRefreshToken } }),
prisma.refreshToken.create({
data: {
userId: user.id,
token: refreshToken,
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
},
}),
]);
auditLog({
userId: user.id,