Skip to main content
O Better Auth roda dentro do seu app e contra o seu próprio banco. O UserKit precisa saber qual dos seus usuários está na página, e não vai aceitar a palavra da página — o seu servidor assina a afirmação.
O identity secret nunca entra no bundle. Nunca prefixe com NEXT_PUBLIC_, nunca renderize no HTML, nunca mande para o navegador para economizar uma ida e volta. Quem tem esse segredo emite sessão verificada para qualquer um dos seus usuários.
O contrato é o da página de identidade federada, e nada aqui o altera:

O que o Better Auth fornece

Um valor: session.user.id. É esse o external_id.
lib/better-auth.ts
getSession valida contra o banco em vez de decodificar o cookie. Aqui a tentação é a maior de todas, porque a tabela de sessão está ali do lado — mas um id que o navegador poderia escolher não é algo que se assine.

A metade do servidor

app/api/userkit-boot/route.ts

A metade do cliente

getState().verified só é true quando o HMAC conferiu. Logado no Better Auth com verified: false significa que o segredo é do outro ambiente ou que a mensagem assinada não era exatamente o external_id.

Configuração

O que não viaja

O usuário do Better Auth carrega email e emailVerified. São afirmações sobre o seu banco, e não viram identidade no UserKit: um e-mail enviado pelo /v1/boot é guardado como atributo, não resolve para um contato existente e não vira aresta de identidade. O HMAC prova o external_id e só ele. Para provar um endereço, mande um magic link ou um código por e-mail — os dois fluxos que chegam nele.

O exemplo completo

Um app Next executável com esses arquivos, um .env.example e as partes que esta página deixa de fora.