Autorizar é responder "você pode fazer isto?"
A autenticação diz quem você é; a autorização decide o que você tem permissão de fazer. São dois passos distintos, e eles se refletem em dois códigos de status:
- 401 Não autorizado: não sei quem você é (o token está faltando ou é inválido).
- 403 Proibido: sei quem você é, mas você não tem permissão para isto.
Um erro muito comum é devolver 401 quando na verdade cabe 403. Se o usuário já está autenticado e simplesmente lhe falta a permissão, é 403.
Middleware que exige um token válido
O primeiro middleware lê o cabeçalho Authorization. Se faltar —ou se o token
não for válido porque a assinatura não bate— ele corta com 401. Se for
válido, guarda o usuário em req.usuario para que os passos seguintes saibam quem é.
function requerAuth(req, res, next) {
const cabecalho = req.headers.authorization;
// verificarToken devolve o payload, ou null se a assinatura não bater.
const usuario = cabecalho ? verificarToken(cabecalho, SEGREDO) : null;
if (!usuario) {
res.status(401).json({ error: "Não autorizado" });
return; // corta: não chama next()
}
req.usuario = usuario;
next();
}
Num caso real, o cabeçalho é "Bearer <token>": separa-se o esquema
(Bearer) do token antes de verificá-lo. Para os exercícios vamos mandar o token
diretamente no cabeçalho para focar na lógica.
Middleware de papéis
A autorização por papel se resolve com uma fábrica de middleware: uma função
que recebe o papel exigido e devolve o middleware concreto. Assim você pode
escrever requerPapel("admin") em qualquer rota.
function requerPapel(papel) {
return function (req, res, next) {
if (!req.usuario || req.usuario.papel !== papel) {
res.status(403).json({ error: "Sem permissão" });
return;
}
next();
};
}
Eles são encadeados em ordem: primeiro requerAuth (para que exista
req.usuario), depois requerPapel("admin"):
app.delete("/usuarios/:id", requerAuth, requerPapel("admin"), removerUsuario);
Exemplos
Encadear autenticação e papel
function requerPapel(papel) {
return function (req, res, next) {
if (!req.usuario || req.usuario.papel !== papel) {
res.status(403).json({ error: "Sem permissão" });
return;
}
next();
};
}
const soAdmin = requerPapel("admin");
const req = { usuario: { papel: "leitor" } };
const res = {
status(c) { this.code = c; return this; },
json(b) { console.log(this.code, JSON.stringify(b)); },
};
soAdmin(req, res, () => console.log("acesso concedido"));