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.