Verificação de identidade
Sua write key pública identifica seu projeto, mas não autentica ninguém: qualquer um pode abrir um console de navegador e enviar eventos como distinct_id: "[email protected]". A verificação de identidade fecha esse buraco — seu backend assina um JWT de vida curta provando que este navegador realmente é este usuário, e o Kilden o verifica em cada evento identificado.
O tráfego anônimo não é afetado: não há identidade a forjar, então eventos anônimos nunca precisam de token.
Como funciona
Seção intitulada “Como funciona”- Nas configurações do projeto você cria um identity secret (separado das suas write keys). Cada secret tem um
kid(key id), e vários podem estar ativos ao mesmo tempo, então a rotação não tem janela de transição. - No login, seu backend assina um JWT com esse secret — HS256, com o id do usuário em
sub. - O SDK envia o token com cada batch de eventos como
Authorization: Bearer <token>. - O pipeline o verifica: assinatura contra um
kidativo,expválido esubigual aodistinct_iddo evento. O resultado é armazenado em cada evento comoverified.
O token
Seção intitulada “O token”Payload de claims:
{ "sub": "user_4821", "iat": 1752192000, "exp": 1752195600, "traits": { "plan": "pro" }}sub— obrigatório. Deve ser igual aodistinct_idque o navegador vai usar (o que você passa paraidentify()).exp— obrigatório. Mantenha-o curto (minutos a horas); o SDK renova automaticamente.kid— obrigatório, no header do JWT (não no payload). Identifica qual identity secret do projeto assinou o token.traits— opcional. Traits assinados, aplicados com verificação do servidor.- Algoritmo: somente HS256. Tokens assinados com qualquer outra coisa (incluindo
none) falham na verificação.
Assinando no seu backend
Seção intitulada “Assinando no seu backend”import jwt from 'jsonwebtoken';
// Das configurações do projeto → Verificação de identidade.// O secret nunca sai do seu backend.const KILDEN_IDENTITY_SECRET = process.env.KILDEN_IDENTITY_SECRET;const KILDEN_IDENTITY_KID = process.env.KILDEN_IDENTITY_KID;
app.get('/api/kilden-token', requireAuth, (req, res) => { const token = jwt.sign( { sub: req.user.id, // deve bater com o id que você passa para kilden.identify() traits: { plan: req.user.plan }, }, KILDEN_IDENTITY_SECRET, { algorithm: 'HS256', expiresIn: '1h', keyid: KILDEN_IDENTITY_KID }, ); res.json({ token });});<?php
use Firebase\JWT\JWT;
// Das configurações do projeto → Verificação de identidade.$secret = getenv('KILDEN_IDENTITY_SECRET');$kid = getenv('KILDEN_IDENTITY_KID');
function kildenIdentityToken(string $userId, array $traits = []): string{ $now = time();
$payload = [ 'sub' => $userId, // deve bater com o id passado para kilden.identify() 'iat' => $now, 'exp' => $now + 3600, 'traits' => (object) $traits, ];
return JWT::encode($payload, $GLOBALS['secret'], 'HS256', $GLOBALS['kid']);}(Usa firebase/php-jwt; o quarto argumento define o header kid.)
Conectando o SDK
Seção intitulada “Conectando o SDK”Deixe o SDK gerenciar o ciclo de vida do token — ele renova cerca de um minuto antes do exp e tenta de novo uma vez ao receber 401:
kilden.init('YOUR_WRITE_KEY', { getIdentityToken: async () => { const res = await fetch('/api/kilden-token'); if (!res.ok) return null; return (await res.json()).token; },});
// depois do login:kilden.identify('user_4821');Alternativas: passe um token que você já tem no init (identityToken: '...'), por chamada (identify(id, traits, { token })) ou de forma imperativa (setIdentityToken(token)). No logout, reset() o limpa.
O token viaja por batch, no header Authorization: Bearer. Uma exceção documentada: o flush de fim de página pode cair para sendBeacon, que não carrega headers, então o token vai no corpo como identity_token — mesma proteção TLS, verificado em segundo lugar.
Modos de enforcement
Seção intitulada “Modos de enforcement”A verificação é sempre computada — todo evento identificado recebe verified: true/false independentemente do modo. O modo governa apenas o que acontece com mutações de identidade não verificadas ($identify, $set, $set_once):
| Modo | Mutações de identidade não verificadas de usuários identificados |
|---|---|
off |
Aplicadas normalmente |
monitor |
Aplicadas normalmente, mas cada uma é contabilizada para você ver exatamente o que enforce bloquearia |
enforce |
Não aplicadas: não podem criar pessoas, vincular identidades nem escrever traits. A resolução de identidade para eventos identificados não verificados vira somente leitura — mapeamentos existentes continuam atribuindo, mas nada novo é criado |
Como monitor mede precisamente o que enforce bloquearia, o rollout seguro é: instrumente o token → observe o contador de não verificados cair a zero → mude para enforce. A mudança não altera dado nenhum, só o comportamento.
Duas regras valem em todos os modos:
- Eventos nunca são descartados. Uma verificação que falha mantém o evento com
verified: false; ele é excluído dos consumidores sensíveis a confiança (gatilhos de campanha, e leituras do messenger quando mensageria em canais identificados for lançada), mas permanece no seu analytics. - Eventos anônimos sempre passam. Seu
verified: falseé uma convenção (não há nada a verificar), não desconfiança. Eventos server-side enviados com uma secret key sãoverified: true— a secret key é a autenticação.
Traits assinados
Seção intitulada “Traits assinados”Traits dentro do JWT são aplicados como um $set verificado pelo servidor e têm prioridade sobre traits não assinados no mesmo evento. Use-os para valores que o navegador não deveria poder afirmar sobre si mesmo (plano, papel, status da conta). Para fatos que movimentam dinheiro ou mensageria, prefira enviar o próprio evento server-side.
Rotação
Seção intitulada “Rotação”Crie um novo secret (novo kid) nas configurações do projeto, faça o deploy do seu backend assinando com ele e então desative o kid antigo. Vários secrets ativos significam rotação sem downtime; tokens assinados por um kid desativado falham na verificação imediatamente.