Saltar al contenido principal

Quem entrou, no código

A cada requisição, a plataforma entrega à aplicação a identidade de quem entrou, assinada. O SDK de TypeScript a confere e devolve a pessoa; em outra linguagem, a conferência é a mesma e está no protocolo de runtime.

Instalar​

Baixe o pacote de TypeScript em zero.nnumbers.com.br/downloads e instale o arquivo:

npm install ./zero-sdk-typescript.tgz

No servidor: @nnumbers/zero/app​

import { NNumbers, UnauthenticatedError } from '@nnumbers/zero/app'

const nn = NNumbers.init() // lê as variáveis NNUMBERS_*

app.get('/api/me', async (req, res) => {
res.json({ user: await nn.auth.user(req) }) // a pessoa, ou null
})

app.get('/painel', async (req, res) => {
try {
const user = await nn.auth.requireUser(req, req.url)
res.send(`Olá, ${user.name ?? user.username}`)
} catch (e) {
if (e instanceof UnauthenticatedError) return res.redirect(e.loginPath)
throw e
}
})
APIO que faz
NNumbers.init()o contexto da aplicação: appId, org e auth
nn.auth.user(req)quem entrou, ou null
nn.auth.requireUser(req, returnTo)como user, mas sem pessoa lança UnauthenticatedError com o loginPath que volta a returnTo
nn.auth.loginPath(returnTo)o caminho do login; destino fora da aplicação vira /
nn.auth.logoutPatho caminho da saída (POST, a partir de um formulário da própria aplicação)
nn.auth.sessionPatho estado da sessão, para o navegador

user aceita a requisição do Node, a Request do fetch ou um objeto de cabeçalhos. Há um exemplo completo, sem framework, em examples/organization-iam no repositório do SDK.

ErroCódigoQuando
AppConfigurationErrorORGANIZATION_IAM_NOT_ENABLEDa aplicação roda sem a capacidade ligada, ou fora do Zero
UnauthenticatedErrorUSER_SESSION_REQUIREDa rota exige alguém e ninguém entrou
IdentityAssertionErrorIDENTITY_ASSERTION_INVALIDchegou uma identidade que não confere — nunca vira pessoa

Na interface: @nnumbers/zero/react​

Componentes e hooks para React 18 ou 19 (react é dependência opcional). Eles leem a sessão que a plataforma guarda e levam aos caminhos reservados; nenhum vê token. A interface mostra quem entrou — quem decide é o servidor, com nn.auth.user(req).

import { NNumbersProvider, Authenticated, Unauthenticated, LoginButton, UserMenu, useUser, useOrganization } from '@nnumbers/zero/react'

export function App() {
return (
<NNumbersProvider>
<header><UserMenu /></header>
<Authenticated fallback={<LoginButton>Entrar com a organização</LoginButton>}>
<Painel />
</Authenticated>
<Unauthenticated>
<p>Entre com a conta da organização.</p>
</Unauthenticated>
</NNumbersProvider>
)
}

function Painel() {
const user = useUser() // SessionUser | null | undefined (carregando)
const org = useOrganization() // { id, slug }
return <p>Olá, {user?.name} — {org?.slug}</p>
}
APIO que faz
<NNumbersProvider>lê a sessão uma vez e a entrega abaixo; initialSession evita a busca (renderização no servidor, testes)
useAuth(){ user, organization, loading, error, refresh(), loginPath(returnTo?), logoutPath }
useUser()quem entrou; null se ninguém; undefined enquanto carrega
useOrganization()a organização dona da aplicação
<Authenticated fallback?>o conteúdo para quem entrou, o fallback para quem não entrou, nada enquanto carrega
<Unauthenticated>o conteúdo para quem NÃO entrou; nada para quem entrou, nem enquanto carrega
<LoginButton returnTo?>link para o login da organização, voltando à página atual (ou a returnTo)
<LogoutButton>formulário POST para a saída
<UserMenu>o nome de quem entrou e a saída
readSession()a mesma leitura, sem React

Em outra linguagem​

A identidade chega no cabeçalho X-NNumbers-Identity: um JWS compacto, algoritmo ES256, typ nn-identity+jwt. Confira sempre, em toda requisição — um cabeçalho sem assinatura conferida não prova nada:

  1. A assinatura, com as chaves públicas do endereço em NNUMBERS_IDENTITY_JWKS. Guarde as chaves por alguns minutos e busque de novo quando chegar um kid desconhecido.
  2. iss igual a NNUMBERS_IDENTITY_ISSUER.
  3. aud igual a NNUMBERS_APP_ID — a identidade entregue a outra aplicação não vale aqui.
  4. org igual a NNUMBERS_ORG_ID.
  5. nbf e exp: a identidade vale por 5 minutos, com até 60 s de tolerância de relógio.

Sem o cabeçalho, a requisição é anônima. Com o cabeçalho e qualquer conferência falhando, recuse — nunca trate como pessoa.

ClaimO que é
subo identificador da pessoa no IAM da organização
org, org_sluga organização
iamo endereço do IAM da organização
sida referência da sessão
name, email, email_verified, preferred_usernamequando a conta os tem
iat, nbf, exp, jtio prazo e o identificador desta identidade

O protocolo de runtime descreve os caminhos reservados, o broker e a consulta ao QueryMesh em outra linguagem.

As variáveis da plataforma​

Com a capacidade ligada, a publicação injeta:

VariávelO que é
NNUMBERS_APP_IDo id desta aplicação (svc_…)
NNUMBERS_ORG_ID, NNUMBERS_ORG_SLUGa organização do projeto
NNUMBERS_IDENTITY_ISSUERo emissor da identidade
NNUMBERS_IDENTITY_JWKSo endereço das chaves públicas — alcançável só de dentro da plataforma
NNUMBERS_BROKER_URLo endereço do broker, onde a aplicação consulta o QueryMesh em nome de quem entrou — alcançável só de dentro da plataforma

O prefixo NNUMBERS_ é da plataforma: a configuração do serviço não aceita variável com ele.

Próximos passos​