Verificação de identidade
Reconheça uma pessoa autenticada e restaure o histórico de conversas entre dispositivos, usando uma assinatura que o seu backend controla.
Por que verificar#
Por padrão, o SDK é anônimo: gera um visitor_id estável e o salva no keystore da plataforma. Isso basta para uma conversa em um dispositivo. Para reconhecer um usuário específico, restaurar o histórico quando ele se autentica de novo ou em outro dispositivo, e associar de forma confiável uma conversa a um perfil de contato, o backend precisa de prova de que o cliente é quem afirma ser. Se o SDK simplesmente enviasse “sou o usuário 42”, qualquer pessoa poderia forjar outro id e ler o chat de outra pessoa — por isso o Respondo exige uma assinatura criptográfica, userHash, que só o seu backend consegue produzir.
Obter o identity secret#
O identity_secret é uma string secreta associada ao seu agente (o worker de IA ao qual o canal do seu widget está conectado). Gere-o no dashboard, em Channels → Widget → Identity verification. Como vive no agente, é compartilhado por todos os canais atendidos por esse agente — tanto o widget web quanto o SDK móvel. Concede o direito de assinar identidades, por isso deve viver apenas no seu backend e nunca deve ser enviado no app.
A fórmula do userHash#
O userHash é um HMAC-SHA256 sobre uma única string de identidade assinada, codificada em hexadecimal minúsculo:
userHash = HMAC_SHA256( identity_secret, payload )
payload = userId // se userId estiver definido
= email // caso contrário, se email estiver definido
= (invalid) // se ambos estiverem vazios, não há nada para assinar- O segredo é a chave do HMAC; a string de identidade é a mensagem — e não o contrário.
- Assine exatamente uma string — o
userIdem bruto (ou o e-mail), sem salt nem envelope JSON. - Se você passar tanto
userIdquanto e-mail, assine ouserId(tem prioridade). - A saída é hexadecimal (64 caracteres para SHA-256), não base64.
Exemplos de backend#
Calcule a assinatura no seu backend e entregue o userHash pronto ao app.
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
// HMAC_SHA256(identity_secret, userId) em hexadecimal minúsculo.
func ComputeUserHash(identitySecret, userID string) string {
mac := hmac.New(sha256.New, []byte(identitySecret))
mac.Write([]byte(userID))
return hex.EncodeToString(mac.Sum(nil))
}const crypto = require("crypto");
// Retorna o userHash que deve ser passado ao Respondo.identify no cliente móvel.
function computeUserHash(identitySecret, userId) {
return crypto
.createHmac("sha256", identitySecret)
.update(userId, "utf8")
.digest("hex");
}import hmac
import hashlib
# Retorna o userHash que deve ser passado ao Respondo.identify no cliente móvel.
def compute_user_hash(identity_secret: str, user_id: str) -> str:
return hmac.new(
identity_secret.encode(),
user_id.encode(),
hashlib.sha256,
).hexdigest()<?php
// Retorna o userHash que deve ser passado ao Respondo.identify no cliente móvel.
function computeUserHash(string $identitySecret, string $userId): string {
return hash_hmac('sha256', $userId, $identitySecret);
}Como o hash chega ao Respondo#
/identity para chamar nem nada para registrar. O userHash é um campo que viaja nas requisições que o SDK já faz.São dois saltos, e só o primeiro é da sua responsabilidade:
- O seu backend → o seu app. Entrega o hash como preferir. A opção mais barata é um campo adicional na resposta de login/inicialização que o app já recebe — sem requisição extra. Um endpoint dedicado no seu próprio backend (por exemplo
POST /myapp/identityque retorna{ userId, userHash }) funciona igualmente bem. O Respondo não hospeda esse endpoint — é você que o implementa. - O seu app → o Respondo. Isso o SDK faz por você. Assim que você chamar
identify, o SDK anexa o hash a todas as requisições relevantes e o backend o verifica de novo a cada vez.
POST /api/v1/chat body identity.userHash
GET /api/v1/chat/resume query user_hash
GET /api/v1/chat/history query user_hash
GET /api/v1/chat/ws frames user_hash (frames JSON de subscribe/identify após conectar — não na URL do handshake)
GET /api/v1/widget/tours query user_hash
GET /api/v1/widget/checklists query user_hash
POST /api/v1/widget/push/register body user_hashO hash é reverificado em cada requisição, não trocado uma única vez por uma sessão — é isso que torna um userId roubado inútil por si só.
identify nunca é chamado e o chat roda de forma anônima. Isso é comportamento esperado, não um erro do Respondo — um 404 no seu próprio caminho é uma tarefa do seu lado, não uma integração quebrada.Passar a identidade ao SDK#
Obtenha a identidade assinada do seu backend e depois passe o userHash ao identify em qualquer plataforma:
Respondo.identify(
RespondoIdentity(userId = "42", email = "user@example.com", userHash = hash),
)Respondo.identify(
RespondoIdentity(userId: "42", email: "user@example.com", userHash: hash)
)Respondo.identify(RespondoIdentity(
userId: '42', email: 'user@example.com', userHash: hash,
));Comportamento com userHash inválido#
Quando a verificação está ativada no agente e a assinatura está ausente ou errada, o backend faz uma degradação silenciosa para anônimo: o chat continua funcionando, o visitor_id é mantido, e a conversa é associada ao contato anônimo — mas não há vínculo com o perfil nem histórico entre dispositivos. Se um usuário “não é reconhecido”, é quase sempre a assinatura: verifique que assinou o userId (não o e-mail nem JSON), que usou o identity_secret certo, e que emitiu hexadecimal minúsculo. Se o identity_secret do agente estiver vazio, a verificação está desligada e userId / e-mail são aceites tal como estão.
Rodar o identity_secret é, na prática, uma migração abrupta: todos os hashes produzidos com o segredo antigo deixam de verificar de imediato, por isso os usuários já autenticados voltam silenciosamente a anônimo até o seu backend recalcular e voltar a fornecer o userHash com o novo segredo. Rode o segredo apenas quando puder atualizar o lado da assinatura na mesma janela.