Verifica dell’identità
Riconosci una persona autenticata e ripristina la cronologia delle sue conversazioni su più dispositivi, usando una firma controllata dal tuo backend.
Perché verificare#
Per impostazione predefinita l’SDK è anonimo: genera un visitor_id stabile e lo conserva nel keystore della piattaforma. È sufficiente per una conversazione su un dispositivo. Per riconoscere un utente specifico, ripristinare la cronologia al nuovo accesso o su un altro dispositivo, e legare in modo affidabile una conversazione a un profilo di contatto, il backend ha bisogno della prova che il client sia chi dichiara di essere. Se l’SDK inviasse semplicemente «sono l’utente 42», chiunque potrebbe falsificare un altro id e leggere la chat di qualcun altro — perciò Respondo richiede una firma crittografica, userHash, che solo il tuo backend può produrre.
Ottenere l’identity secret#
L’identity_secret è una stringa segreta legata al tuo agente (il worker IA a cui è connesso il canale del tuo widget). Generalo nella dashboard in Channels → Widget → Identity verification. Poiché risiede sull’agente, è condiviso da ogni canale collegato a quell’agente — sia il widget web sia l’SDK mobile. Concede il diritto di firmare le identità, quindi deve risiedere solo sul tuo backend e non va mai incluso nell’app.
La formula di userHash#
userHash è un HMAC-SHA256 su un’unica stringa di identità firmata, codificato in esadecimale minuscolo:
userHash = HMAC_SHA256( identity_secret, payload )
payload = userId // se userId è impostato
= email // altrimenti, se email è impostata
= (non valido) // se entrambi sono vuoti, non c'è nulla da firmare- Il secret è la chiave HMAC; la stringa di identità è il messaggio — non il contrario.
- Firma esattamente una stringa — il
userIdgrezzo (o l’email), senza salt né wrapper JSON. - Se passi sia
userIdsia email, firma louserId(ha la priorità). - L’output è esadecimale (64 caratteri per SHA-256), non base64.
Esempi per il backend#
Calcola la firma sul tuo backend e passa lo userHash già pronto all’app.
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
// HMAC_SHA256(identity_secret, userId) come esadecimale minuscolo.
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");
// Restituisce lo userHash da passare a Respondo.identify sul client mobile.
function computeUserHash(identitySecret, userId) {
return crypto
.createHmac("sha256", identitySecret)
.update(userId, "utf8")
.digest("hex");
}import hmac
import hashlib
# Restituisce lo userHash da passare a Respondo.identify sul client mobile.
def compute_user_hash(identity_secret: str, user_id: str) -> str:
return hmac.new(
identity_secret.encode(),
user_id.encode(),
hashlib.sha256,
).hexdigest()<?php
// Restituisce lo userHash da passare a Respondo.identify sul client mobile.
function computeUserHash(string $identitySecret, string $userId): string {
return hash_hmac('sha256', $userId, $identitySecret);
}Come l’hash arriva a Respondo#
/identity da chiamare e non c’è nulla da registrare. Lo userHash è un campo che viaggia sulle richieste che l’SDK già effettua.Due passaggi, e solo il primo devi costruirlo tu:
- Il tuo backend → la tua app. Consegni l’hash come preferisci. L’opzione più economica è un campo aggiuntivo nella risposta di login/bootstrap che già restituisci — nessun round trip in più. Un endpoint dedicato sul tuo backend (ad esempio
POST /myapp/identityche restituisce{ userId, userHash }) funziona altrettanto bene. Respondo non ospita quell’endpoint — lo implementi tu. - La tua app → Respondo. Se ne occupa l’SDK. Una volta chiamato
identify, l’SDK allega l’hash a ogni richiesta pertinente e il backend lo riverifica ogni volta.
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 (subscribe/identify JSON frames after connect — not in the handshake URL)
GET /api/v1/widget/tours query user_hash
GET /api/v1/widget/checklists query user_hash
POST /api/v1/widget/push/register body user_hashL’hash viene riverificato a ogni richiesta, non scambiato una volta sola per una sessione — è questo che rende inutile di per sé un userId rubato.
identify non viene mai chiamato e la chat procede in modo anonimo. È un comportamento previsto, non un errore di Respondo: un 404 su un tuo percorso è un to-do dalla tua parte, non un’integrazione rotta.Passare l’identità all’SDK#
Recupera l’identità firmata dal tuo backend, poi passa lo userHash a identify su qualsiasi piattaforma:
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 con userHash non valido#
Quando la verifica è abilitata sull’agente e la firma manca o è errata, il backend esegue un downgrade silenzioso ad anonimo: la chat continua a funzionare, il visitor_id viene mantenuto e la conversazione è legata al contatto anonimo — ma non c’è alcun collegamento al profilo né cronologia tra dispositivi. Se un utente «non viene riconosciuto», quasi sempre è la firma: verifica di aver firmato lo userId (non l’email né JSON), di aver usato l’ identity_secret giusto e di aver emesso esadecimale minuscolo. Se l’ identity_secret dell’agente è vuoto, la verifica è disattivata e userId / email vengono accettati così come sono.
Ruotare l’ identity_secret è di fatto un cambio netto: ogni hash prodotto con il vecchio secret smette di verificarsi all’istante, quindi gli utenti già autenticati ripiegano silenziosamente su anonimo finché il tuo backend non ricalcola e rifornisce il loro userHash con il nuovo secret. Ruota il secret solo quando puoi aggiornare il lato firma nella stessa finestra.