~/VibeHandbook
PDF gratis

Capítulo 18 · 04

Autenticación vs. autorización: el endpoint que cualquiera puede llamar

Estas dos palabras suenan parecido, y la diferencia entre ellas es donde viven las brechas reales.

  • Autenticación es ¿quién eres? — iniciar , demostrar identidad.
  • Autorización es ¿qué se te permite hacer? — si este usuario ya identificado puede realizar esta acción sobre estos datos.

La IA es decente en autenticación; las bibliotecas se encargan de la mayor parte. La autorización es donde falla sistemáticamente, porque la autorización es específica de las reglas de tu app, y la IA no las conoce. El desastre de manual:

// VULNERABLE: checks you're logged in, but not WHO you are
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  res.json(db.getAllUsers()); // any logged-in user can hit this
});

Ese está "protegido": tienes que haber iniciado sesión. Pero cualquier usuario con sesión iniciada, incluido uno que se registró hace treinta segundos, puede llamarlo y descargar los datos de todos los usuarios. Autenticación presente, autorización ausente. La solución es verificar el permiso sobre la acción en sí:

// SAFE: confirms this user is actually an admin
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  if (!req.user.isAdmin) return res.status(403).send("Forbidden");
  res.json(db.getAllUsers());
});

Piensa en dos puertas que una petición debe atravesar. La autenticación pregunta "¿has iniciado sesión?"; la autorización pregunta "¿se te permite a ti hacer esto?" La brecha ocurre cuando una app construye la primera puerta y se olvida de la segunda:

  request ──▶ ┌──────────────────┐  ──▶ ┌──────────────────┐  ──▶  action
              │ AUTHENTICATION   │      │ AUTHORIZATION     │       runs
              │ "logged in?"     │      │ "may THIS user    │
              │                  │      │  do THIS action?" │
              └──────────────────┘      └──────────────────┘
                  ✓ most apps              ✗ often missing
                    build this               → the breach

  EXAMPLE — /admin/export-all-users
     logged-in user  ──▶ [auth ✓] ──▶ [ no authz check ] ──▶ ALL users dumped
     logged-in user  ──▶ [auth ✓] ──▶ [ isAdmin? → 403  ] ──▶ blocked  ✓

La misma trampa aparece en miniatura por todas partes: un endpoint que devuelve el pedido #1234 sin verificar que ese pedido pertenece al usuario que hace la petición. Cualquiera puede cambiar el número en la y leer el pedido de otra persona. La regla no tiene nada de glamurosa, pero es absoluta: verifica la autorización en cada endpoint que toque datos, y no confíes en un ID que venga del cliente. No asumas que una URL oculta es segura solo porque está oculta — "nadie sabe que esto existe" no es un control de seguridad.

¿Lo quieres sin conexión?

Descarga el libro entero en PDF o EPUB — gratis.