Autorizar es responder "¿puedes hacer esto?"
La autenticación dice quién eres; la autorización decide qué te está permitido. Son dos pasos distintos, y se reflejan en dos códigos de estado:
- 401 No autorizado: no sé quién eres (falta el token o no es válido).
- 403 Prohibido: sé quién eres, pero no tienes permiso para esto.
Un error muy común es devolver 401 cuando en realidad toca 403. Si el usuario ya está autenticado y simplemente le falta el permiso, es 403.
Middleware que exige un token válido
El primer middleware lee la cabecera Authorization. Si falta —o si el token no
es válido porque la firma no cuadra— corta con 401. Si es válido, guarda el
usuario en req.usuario para que los siguientes pasos sepan quién es.
function requiereAuth(req, res, next) {
const cabecera = req.headers.authorization;
// verificarToken devuelve el payload, o null si la firma no cuadra.
const usuario = cabecera ? verificarToken(cabecera, SECRETO) : null;
if (!usuario) {
res.status(401).json({ error: "No autorizado" });
return; // corta: no llama a next()
}
req.usuario = usuario;
next();
}
En un caso real, la cabecera es "Bearer <token>": se separa el esquema
(Bearer) del token antes de verificarlo. Para los ejercicios mandaremos el
token directamente en la cabecera para centrarnos en la lógica.
Middleware de roles
La autorización por rol se resuelve con una fábrica de middleware: una
función que recibe el rol exigido y devuelve el middleware concreto. Así
puedes escribir requiereRol("admin") en cualquier ruta.
function requiereRol(rol) {
return function (req, res, next) {
if (!req.usuario || req.usuario.rol !== rol) {
res.status(403).json({ error: "Sin permiso" });
return;
}
next();
};
}
Se encadenan en orden: primero requiereAuth (para que exista req.usuario),
luego requiereRol("admin"):
app.delete("/usuarios/:id", requiereAuth, requiereRol("admin"), borrarUsuario);
Ejemplos
Encadenar autenticación y rol
function requiereRol(rol) {
return function (req, res, next) {
if (!req.usuario || req.usuario.rol !== rol) {
res.status(403).json({ error: "Sin permiso" });
return;
}
next();
};
}
const soloAdmin = requiereRol("admin");
const req = { usuario: { rol: "lector" } };
const res = {
status(c) { this.code = c; return this; },
json(b) { console.log(this.code, JSON.stringify(b)); },
};
soloAdmin(req, res, () => console.log("acceso concedido"));