fix(auth): comprobar el rol de la sesion en todas las rutas #7

Merged
jpbeldomenico merged 1 commits from fix/verificar-rol-de-sesion into main 2026-08-05 17:02:52 -03:00
Owner

El agujero

Las tres sesiones (admin, cliente, jefe) se firman con el mismo secreto y verificarSesion solo validaba la firma, nunca el role que viaja en el token. Un token de cualquier rol, puesto en la cookie de otro, pasaba la verificacion.

Medido contra la app antes del cambio:

antes despues
token de admin en cliente_session → /api/cliente/autos 200 401
token de jefe en cliente_session → /cliente/dashboard 200 307

No se filtraban datos ajenos, porque todas las consultas se filtran por el sub del token y el id de un admin no existe como cliente. Pero los endpoints quedaban alcanzables, y bastaba una consulta futura menos cuidadosa para que si importara.

El cambio

  • Las 26 llamadas a verificarSesion pasan el rol esperado.
  • El middleware hacia su propio jwtVerify sin mirar el rol: ahora tambien lo comprueba.
  • Se sacan las comprobaciones sueltas sesion.role !== "jefe" de las rutas de jefe, que quedaron redundantes.

Matriz probada contra la app

Con tokens firmados a mano con el secreto local, uno por rol:

  • Cada rol en su area: cliente → /api/cliente/perfil 200, jefe → /api/jefe/servicios 200, admin → /api/admin/servicios 200.
  • Cruzados, todos 401: jefe→cliente/perfil, admin→cliente/autos, cliente→jefe/servicios, cliente→admin/clientes, jefe→admin/turnos.
  • Paginas: jefe→/cliente/dashboard 307, cliente→/admin/dashboard 307, cliente→/cliente/dashboard 200.

tsc, lint, test:bot, test:envio y next build: limpios.

🤖 Generated with Claude Code

## El agujero Las tres sesiones (`admin`, `cliente`, `jefe`) se firman con el **mismo secreto** y `verificarSesion` solo validaba la firma, nunca el `role` que viaja en el token. Un token de cualquier rol, puesto en la cookie de otro, pasaba la verificacion. Medido contra la app antes del cambio: | | antes | despues | |---|---|---| | token de admin en `cliente_session` → `/api/cliente/autos` | **200** | 401 | | token de jefe en `cliente_session` → `/cliente/dashboard` | **200** | 307 | No se filtraban datos ajenos, porque todas las consultas se filtran por el `sub` del token y el id de un admin no existe como cliente. Pero los endpoints quedaban alcanzables, y bastaba una consulta futura menos cuidadosa para que si importara. ## El cambio - Las **26 llamadas** a `verificarSesion` pasan el rol esperado. - El **middleware** hacia su propio `jwtVerify` sin mirar el rol: ahora tambien lo comprueba. - Se sacan las comprobaciones sueltas `sesion.role !== "jefe"` de las rutas de jefe, que quedaron redundantes. ## Matriz probada contra la app Con tokens firmados a mano con el secreto local, uno por rol: - Cada rol en su area: cliente → `/api/cliente/perfil` 200, jefe → `/api/jefe/servicios` 200, admin → `/api/admin/servicios` 200. - Cruzados, todos 401: jefe→cliente/perfil, admin→cliente/autos, cliente→jefe/servicios, cliente→admin/clientes, jefe→admin/turnos. - Paginas: jefe→`/cliente/dashboard` 307, cliente→`/admin/dashboard` 307, cliente→`/cliente/dashboard` 200. `tsc`, `lint`, `test:bot`, `test:envio` y `next build`: limpios. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpbeldomenico added 1 commit 2026-08-05 16:46:02 -03:00
fix(auth): comprobar el rol de la sesion en todas las rutas
Revisión con IA / ai-review (pull_request) Successful in 1m24s
f4df90ac1e
Las tres sesiones (admin, cliente, jefe) se firman con el mismo secreto, asi que
verificar solo la firma alcanzaba para que un token de un rol pasara por la
cookie de otro. Verificado antes del cambio: un token de admin en
cliente_session daba 200 en /api/cliente/autos, y uno de jefe cargaba
/cliente/dashboard. Despues: 401 y 307.

- Las 26 llamadas a verificarSesion pasan el rol esperado.
- El middleware, que hacia su propio jwtVerify sin mirar el rol, ahora tambien
  lo comprueba.
- Se sacan las comprobaciones sueltas de rol en las rutas de jefe, que quedaron
  redundantes.

Matriz probada contra la app: los tres roles siguen entrando en su area (200) y
ninguno entra en la de los otros, ni por API (401) ni por pagina (307).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ai-bot reviewed 2026-08-05 16:47:07 -03:00
ai-bot left a comment
Collaborator

Inline review

Inline review
@@ -6,3 +6,2 @@
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const sesion = await verificarSesion("jefe_session");
if (!sesion || sesion.role !== "jefe")
const sesion = await verificarSesion("jefe_session", "jefe");
Collaborator

Se eliminó la verificación explícita sesion.role !== 'jefe' confiando en que verificarSesion valide el rol. Está bien si la función lo hace, pero si verificarSesion solo chequea la firma del token y no el rol, un admin o cliente con cookie de jefe podría acceder. ¿La función valida el rol internamente?

#ai-review-inline

Se eliminó la verificación explícita `sesion.role !== 'jefe'` confiando en que `verificarSesion` valide el rol. Está bien si la función lo hace, pero si `verificarSesion` solo chequea la firma del token y no el rol, un admin o cliente con cookie de jefe podría acceder. ¿La función valida el rol internamente? #ai-review-inline
@@ -6,1 +6,3 @@
async function verifyCookie(req: NextRequest, cookieName: string) {
// Las tres sesiones se firman con el mismo secreto, así que además de la firma hay
// que mirar el rol: si no, un token de jefe en la cookie del cliente pasa.
async function verifyCookie(req: NextRequest, cookieName: string, rol: "admin" | "cliente" | "jefe") {
Collaborator

La función verifyCookie ahora requiere el parámetro rol, pero verificarSesion en src/lib/auth-admin.ts no aparece en el diff. Si no se actualizó ahí para aceptar y validar el segundo argumento, todas las rutas API fallarán en runtime.

#ai-review-inline

La función `verifyCookie` ahora requiere el parámetro `rol`, pero `verificarSesion` en `src/lib/auth-admin.ts` no aparece en el diff. Si no se actualizó ahí para aceptar y validar el segundo argumento, todas las rutas API fallarán en runtime. #ai-review-inline
@@ -10,2 +12,2 @@
await jwtVerify(token, SECRET);
return true;
const { payload } = await jwtVerify(token, SECRET);
return (payload as { role?: string }).role === rol;
Collaborator

El cast (payload as { role?: string }) asume que el JWT siempre tiene un campo role. ¿Confirmaste que los tokens generados al loguear (admin, jefe, cliente) incluyen ese claim? Si no, la validación siempre fallará y nadie podrá acceder.

#ai-review-inline

El cast `(payload as { role?: string })` asume que el JWT siempre tiene un campo `role`. ¿Confirmaste que los tokens generados al loguear (admin, jefe, cliente) incluyen ese claim? Si no, la validación siempre fallará y nadie podrá acceder. #ai-review-inline
ai-bot reviewed 2026-08-05 16:47:07 -03:00
ai-bot left a comment
Collaborator

Inline review

Inline review
ai-bot reviewed 2026-08-05 16:47:07 -03:00
ai-bot left a comment
Collaborator

Inline review

Inline review
ai-bot reviewed 2026-08-05 16:47:07 -03:00
ai-bot left a comment
Collaborator

Inline review

Inline review
@@ -6,3 +6,2 @@
export async function GET() {
const sesion = await verificarSesion("jefe_session");
if (!sesion || sesion.role !== "jefe")
const sesion = await verificarSesion("jefe_session", "jefe");
Collaborator

Mismo caso: se quitó el check de rol explícito. Si verificarSesion no valida el rol, esto abre acceso indebido. Verificá la implementación en auth-admin.ts.

#ai-review-inline

Mismo caso: se quitó el check de rol explícito. Si `verificarSesion` no valida el rol, esto abre acceso indebido. Verificá la implementación en `auth-admin.ts`. #ai-review-inline
@@ -5,3 +5,2 @@
export async function GET(req: NextRequest) {
const sesion = await verificarSesion("jefe_session");
if (!sesion || sesion.role !== "jefe")
const sesion = await verificarSesion("jefe_session", "jefe");
Collaborator

Igual que arriba: se confía en verificarSesion('jefe_session', 'jefe') para validar rol. Confirmá que la función lanza 401 si el rol no coincide, no solo si el token es inválido.

#ai-review-inline

Igual que arriba: se confía en `verificarSesion('jefe_session', 'jefe')` para validar rol. Confirmá que la función lanza 401 si el rol no coincide, no solo si el token es inválido. #ai-review-inline
ai-bot reviewed 2026-08-05 16:47:07 -03:00
ai-bot left a comment
Collaborator

Inline review

Inline review
Collaborator

Qué cambia
Se agrega validación de rol en la verificación de sesión: verificarSesion y verifyCookie ahora reciben el rol esperado ("admin" | "cliente" | "jefe") y validan que el payload del JWT coincida. Antes el middleware solo verificaba la firma, permitiendo que un token de un rol accediera a rutas de otro si compartía nombre de cookie.

Riesgos
Cambio de contrato en verificarSesion (parámetro nuevo obligatorio). Si queda alguna llamada sin el segundo argumento, romperá en runtime. El middleware ahora rechaza tokens con rol incorrecto: antes un token de jefe en cliente_session pasaba, ahora no.

Antes de aprobar
Buscar llamadas a verificarSesion sin el segundo parámetro (grep -r "verificarSesion(" --include="*.ts"). Probar login y acceso a rutas de cada rol (admin, cliente, jefe) y confirmar que un token de un rol no accede a rutas de otro. Verificar que pnpm check pase (tipos de TypeScript).

#ai-review-summary

**Qué cambia** Se agrega validación de rol en la verificación de sesión: `verificarSesion` y `verifyCookie` ahora reciben el rol esperado (`"admin" | "cliente" | "jefe"`) y validan que el payload del JWT coincida. Antes el middleware solo verificaba la firma, permitiendo que un token de un rol accediera a rutas de otro si compartía nombre de cookie. **Riesgos** Cambio de contrato en `verificarSesion` (parámetro nuevo obligatorio). Si queda alguna llamada sin el segundo argumento, romperá en runtime. El middleware ahora rechaza tokens con rol incorrecto: antes un token de jefe en `cliente_session` pasaba, ahora no. **Antes de aprobar** Buscar llamadas a `verificarSesion` sin el segundo parámetro (`grep -r "verificarSesion(" --include="*.ts"`). Probar login y acceso a rutas de cada rol (admin, cliente, jefe) y confirmar que un token de un rol no accede a rutas de otro. Verificar que `pnpm check` pase (tipos de TypeScript). #ai-review-summary
jpbeldomenico merged commit 2bdf76ab63 into main 2026-08-05 17:02:52 -03:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpbeldomenico/taller_automotriz#7