Express
Um middleware que autentica e outro que autoriza.
Dois middlewares cobrem quase tudo: um que rejeita um token inválido e outro que rejeita quem não tem o papel. A página do Node explica o que eles chamam por baixo.
Instalação
npm install @nulvless/nulvless-js expressCrie o client
import { createServerClient } from '@nulvless/nulvless-js';
export const nulvless = createServerClient(
process.env.NULVLESS_URL!,
process.env.NULVLESS_SECRET!,
);Autenticação
import type { NextFunction, Request, Response } from 'express';
import { nulvless } from '../lib/nulvless';
export async function requireAuth(req: Request, res: Response, next: NextFunction) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).end();
const { data, error } = await nulvless.auth.verify(undefined, {
headers: { Authorization: `Bearer ${token}` },
});
if (error) return res.status(401).end();
req.session = data.session;
req.userId = data.user.id;
next();
}Tipe a requisição
Para req.userId não ser um erro no TypeScript:
import type { Session } from '@nulvless/nulvless-js';
declare global {
namespace Express {
interface Request {
session?: Session;
userId?: string;
}
}
}Autorização
A mesma chamada, com a pergunta incluída — sem uma segunda ida ao servidor.
export function requireRole(roles: string[]) {
return async (req: Request, res: Response, next: NextFunction) => {
const token = req.headers.authorization?.replace('Bearer ', '');
const { error } = await nulvless.auth.verify(
{ resource: req.params.org, roles },
{ headers: { Authorization: `Bearer ${token}` } },
);
if (error) return res.status(403).end();
next();
};
}
app.delete('/orgs/:org/keys/:id', requireRole(['owner', 'admin']), handler);requireRole também verifica o token, então funciona sozinho. Empilhe depois de
requireAuth só quando o handler também precisar de req.userId.
Aja em nome do usuário
import { forwardUserHeaders } from '@nulvless/nulvless-js';
app.post('/orgs/:org/invites', requireAuth, async (req, res) => {
const { data, error } = await nulvless.auth.grants.invite(
{ invites: [{ email: req.body.email, role_id: req.body.role_id }], resource: req.params.org },
{ headers: forwardUserHeaders(req) },
);
if (error) return res.status(400).json({ error });
res.json(data);
});Um Request do Express é um IncomingMessage do Node, então entra direto.
Exija uma confirmação recente
app.delete('/keys/:id', requireAuth, async (req, res) => {
const { error } = await nulvless.auth.sessions.revoke({
id: req.params.id,
nonce: req.headers['nlv-sudo-nonce'] as string,
});
if (error) return res.status(403).json({ error });
res.status(204).end();
});Esse header carrega o código que o usuário digitou depois de o
auth.sessions.sudo() tê-lo enviado. Gasto assim, ele autoriza só esta chamada e
nunca eleva a sessão. Veja Modo sudo.