Clients
createClient para o navegador, createServerClient para todo o resto.
createClient — navegador
import { createClient, Storage } from '@nulvless/nulvless-js';
const nulvless = createClient(url, publishableKey, options?);urlstringOptionalO issuer do seu ambiente — https://<project>.nulvless.co. Em produção você
pode usar seu domínio personalizado, como
https://api.exemplo.com.
publishableKeystringOptionalChave publicável, começando com pk-.
optionsClientOptionsOptionalOpcional — veja Configuração.
export const nulvless = createClient('https://acme.nulvless.co', 'pk-…', {
storage: Storage.Local,
trackUser: true,
language: () => 'pt-BR',
});A chave publicável pode ir para produção sem risco. Ela só consegue fazer o que o usuário autenticado já conseguiria — não é uma capacidade própria.
Armazenamento de sessão
O client de navegador persiste a sessão para você — no localStorage por
padrão, ou, quando o código roda onde não existe window (SSR, testes), num
armazenamento em memória do próprio client. Escolha outro adaptador com
storage:
import { Storage } from '@nulvless/nulvless-js';
createClient(url, key, { storage: Storage.Local });As chaves têm como padrão nlv-<slug>-token e nlv-<slug>-token-accounts, e
podem ser sobrescritas com storageKeys.
createServerClient — servidor
import { createServerClient } from '@nulvless/nulvless-js';
const nulvless = createServerClient(url, secretKey, options?);urlstringOptionalO issuer do seu ambiente
secretKeystringOptionalChave secreta, começando com sk-
optionsServerClientOptionsOptionalIgual a ClientOptions, menos storage e storageKeys
Nunca mande uma chave secreta para o navegador
Chaves sk- alcançam as partes administrativas da API. Crie o client de
servidor apenas em código de servidor — rotas de API, handlers, workers.
Repassando os headers do usuário
A impressão digital da sessão registra o dispositivo e a localização de onde ela foi criada. No servidor, a requisição que a plataforma enxerga é a do seu servidor, não a do usuário — então esses campos descreveriam a sua infraestrutura.
O forwardUserHeaders copia os headers relevantes da requisição que chegou:
import { createServerClient, forwardUserHeaders } from '@nulvless/nulvless-js';
const nulvless = createServerClient(url, 'sk-…');
const { data, error } = await nulvless.auth.grants.invite(
{ invites: [{ email: '[email protected]', role_id: roleId }], resource: 'acme' },
{ headers: forwardUserHeaders(req) },
);Para aplicar em toda chamada em vez de uma a uma, resolva os headers de forma preguiçosa:
createServerClient(url, key, {
trackUser: true,
headers: () => forwardUserHeaders(cls.get('req')),
});Mantendo as respostas de auth fora dos caches
O forwardUserHeaders cuida da requisição que entra. Este cuida da resposta que
sai.
Sempre que a sua resposta cria, renova ou encerra uma sessão, aplique o
applyAuthCacheHeaders nela:
import { createServerClient, forwardUserHeaders, applyAuthCacheHeaders } from '@nulvless/nulvless-js';
export async function POST(request: Request) {
const { data } = await nulvless.auth.signIn(params, {
headers: forwardUserHeaders(request),
});
const response = NextResponse.json({ ok: true });
response.cookies.set('session', data.access_token);
return applyAuthCacheHeaders(response);
}Ele aceita um Response web (App Router, Workers, Deno) ou um ServerResponse
do Node (Express, Pages Router), e devolve o mesmo objeto para a chamada caber
dentro de um return:
app.post('/login', async (req, res) => {
const { data } = await nulvless.auth.signIn(params, {
headers: forwardUserHeaders(req),
});
applyAuthCacheHeaders(res);
res.cookie('session', data.access_token, { httpOnly: true, sameSite: 'lax' });
res.json({ ok: true });
});Quando o framework aceita um mapa simples de headers, espalhe o
AUTH_CACHE_HEADERS.
Uma resposta de login cacheada entrega a sessão ao próximo visitante
Se uma CDN cacheia uma resposta que carrega um cookie de sessão novo, ela entrega
esse cookie para o próximo visitante. A proteção que você esperaria não vale
aqui: caches compartilhados são proibidos de reusar respostas de requisições que
carregam Authorization, mas a sua é autenticada por cookie, que não tem essa
regra. Isso já aconteceu em produção com CloudFront, Vercel Edge e Cloudflare.
As respostas da API do nulvless já saem com Cache-Control: no-store, então isto
vale apenas para as respostas que o seu app devolve.
Multi-conta
Defina multiUser: true num client de navegador para manter várias contas
autenticadas e alternar entre elas.
const nulvless = createClient(url, key, { multiUser: true });
await nulvless.auth.add(authenticated);
const accounts = await nulvless.auth.list();
await nulvless.auth.switch(userId);
await nulvless.auth.remove(userId);O auth.get() devolve a sessão ativa e o auth.set() a substitui. Isso vem
desligado por padrão — habilite só se o seu produto realmente troca de conta.