Node
O modelo do servidor — uma chave secreta e um token verificado a cada requisição.
Esta página é a versão sem framework: o que o client de servidor faz e por quê. Express e Fastify encaixam as mesmas chamadas nos idiomas de cada um.
Um servidor nunca guarda a sessão de uma pessoa. Ele guarda uma chave secreta e verifica o token que chega em cada requisição.
Instalação
npm install @nulvless/nulvless-jsCrie o client
import { createServerClient } from '@nulvless/nulvless-js';
export const nulvless = createServerClient(
process.env.NULVLESS_URL!,
process.env.NULVLESS_SECRET!,
);Não existe opção storage aqui — persistência é assunto de navegador. Um único
client atende todas as requisições; ele não guarda estado por usuário.
Verifique quem chamou
verify responde duas perguntas de uma vez: este token continua válido, e quem
o porta tem a permissão que você nomeou. Pergunte as duas na mesma chamada, em
vez de buscar o usuário e decidir por conta própria.
import { nulvless } from './nulvless';
export async function authenticate(token: string | undefined) {
if (!token) return null;
const { data, error } = await nulvless.auth.verify(undefined, {
headers: { Authorization: `Bearer ${token}` },
});
return error ? null : data;
}Passar undefined no primeiro argumento verifica apenas o token. Para também
exigir um papel sobre um recurso:
const { error } = await nulvless.auth.verify(
{ resource: orgId, roles: ['owner', 'admin'] },
{ headers: { Authorization: `Bearer ${token}` } },
);Leia o token da requisição
Nada no SDK lê o seu objeto de requisição, porque o formato muda conforme o runtime.
// Request web — Next.js App Router, Deno, Workers
const token = request.headers.get('authorization')?.replace('Bearer ', '');
// IncomingMessage do Node — Express, Fastify (via request.raw), http.createServer
const token = req.headers.authorization?.replace('Bearer ', '');Aja em nome do usuário
Quando o servidor faz algo por alguém — enviar um convite, por exemplo — repasse os headers dessa pessoa, para o registro refletir o dispositivo dela e não a sua infraestrutura.
import { forwardUserHeaders } from '@nulvless/nulvless-js';
await nulvless.auth.grants.invite(
{ invites: [{ email, role_id: roleId }], resource: orgSlug },
{ headers: forwardUserHeaders(request) },
);forwardUserHeaders aceita um Request web ou qualquer coisa com o formato de
um IncomingMessage do Node, então a mesma chamada serve para vários runtimes.
Envie uma mensagem
await nulvless.comms.email.send({
to: '[email protected]',
template: 'grants-invite',
language: 'pt-BR',
params: { organization: 'Acme Inc', role: 'admin' },
});Um servidor http puro
Sem framework nenhum, para mostrar que não há nada escondido:
import { createServer } from 'node:http';
import { nulvless } from './lib/nulvless';
createServer(async (req, res) => {
const token = req.headers.authorization?.replace('Bearer ', '');
const { data, error } = await nulvless.auth.verify(undefined, {
headers: { Authorization: `Bearer ${token}` },
});
if (error) {
res.writeHead(401).end();
return;
}
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ user: data.user.id }));
}).listen(3000);Exigindo uma confirmação recente
Para uma rota destrutiva, exija sudo. O navegador chama auth.sessions.sudo(),
o usuário digita o código, e o navegador manda esse código num header. Seu
handler apenas repassa.
const { error } = await nulvless.auth.sessions.revoke({ id: sessionId, nonce });Veja Modo sudo.