Documentação
Comece a construirQuickstarts por frameworkNode

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-js

Crie o client

lib/nulvless.ts
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.

lib/require-auth.ts
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:

server.ts
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.

Próximos

Nesta página