Verifica dell'identità
Verifica chi sta chattando firmando un JWT per i tuoi utenti connessi. Agentkit verifica il token e collega la conversazione a un Contatto.
La verifica dell'identità ti permette di dire ad Agentkit chi sta chattando. Il tuo backend firma un JWT a breve scadenza per l'utente connesso, il widget passa quel token ad Agentkit, e Agentkit lo verifica e collega la conversazione a un Contatto.
È arricchimento e anti-spoofing, mai un cancello d'accesso. Un token mancante, scaduto o non valido significa semplicemente che il visitatore chatta in modo anonimo — la chat non viene mai bloccata.
Nota: i token di identità contengono dati privati dell'utente. Firmali sempre sul tuo server, mai in JavaScript lato client — firmare nel browser esporrebbe la tua chiave segreta.
Come funziona
- Un utente accede alla tua app.
- Il tuo backend genera un JWT a breve scadenza, firmato con la chiave segreta di identità del tuo agente.
- Passi il token al widget (prima che si carichi, oppure a runtime).
- Il widget invia il token con ogni richiesta di chat.
- Agentkit verifica la firma e i claim, poi crea o aggiorna un Contatto in base al soggetto del token e collega la conversazione a esso.
Attivare la verifica
- Apri il tuo agente e vai su Impostazioni → Identità.
- Attiva Verifica i visitatori connessi (JWT).
- Copia la Chiave segreta di firma.
La chiave segreta di firma è solo lato server — tienila in una variabile d'ambiente e non esporla mai nel codice client. Rigenerare la chiave invalida immediatamente ogni token firmato con quella precedente.
Specifica del token
Firma il token con l'algoritmo HS256. Altri algoritmi (incluso alg: none e le chiavi asimmetriche) vengono rifiutati.
Claim
| Claim | Obbligatorio | Note |
|---|---|---|
sub (o user_id) | Sì | L'id utente immutabile della tua app. Usa un id interno stabile — non un'email, uno username o un id Agentkit. Se sono presenti sia sub che user_id, devono coincidere. |
exp | Sì | Ora di scadenza. Usa token a breve durata (~1 ora). I token con exp oltre 24 ore nel futuro vengono rifiutati. |
aud | Consigliato | Vincola il token a questo agente: agentkit:chatbot:{chatbotId}. Se presente, deve corrispondere. |
email | No | Salvata sul Contatto. |
name | No | Salvata sul Contatto. |
phonenumber | No | Salvato nel campo phone del Contatto. |
custom_attributes | No | Oggetto per qualsiasi dato aggiuntivo (piano, azienda, id Stripe, …). |
Dal token vengono lette solo email, name, phonenumber e custom_attributes. Qualsiasi altro claim di primo livello viene ignorato — inserisci dati extra o di integrazione dentro custom_attributes.
Limiti
email,name,phonenumber: fino a 1024 caratteri ciascuno.custom_attributes: fino a 8192 byte, 50 chiavi e 5 livelli di annidamento.
Un token che viola questi limiti viene verificato come anonimo (l'errore viene registrato nei log) invece di bloccare la chat.
Firmare il token
Funziona qualsiasi libreria JWT (jsonwebtoken, PyJWT, …) — ti serve solo un token HS256 con i claim indicati sopra. Questo esempio usa jose, che gira anche su edge runtime (Vercel Edge, Cloudflare Workers, Deno):
// On YOUR backend, mint a short-lived JWT for your logged-in user.
import { SignJWT } from 'jose';
const secret = new TextEncoder().encode(
process.env.AGENTKIT_CHATBOT_IDENTITY_SECRET,
);
const token = await new SignJWT({
// Optional private profile claims — stored on the Contact, never shown to the
// bot. ONLY these keys are read: email, name, phonenumber, custom_attributes.
// Put extra/integration data (Stripe ids, plan, company, …) in custom_attributes.
email: user.email,
name: user.name,
phonenumber: user.phone, // maps to the Contact's "phone"
custom_attributes: {
plan: user.plan,
stripe_id: user.stripeCustomerId,
},
})
.setProtectedHeader({ alg: 'HS256' })
.setSubject(user.id) // immutable id from YOUR system (not email/username)
.setIssuedAt()
.setExpirationTime('1h') // short-lived; this is a browser bearer token
.setAudience('agentkit:chatbot:YOUR_CHATBOT_ID')
.sign(secret);
Lo stesso snippet, precompilato con l'audience del tuo agente, è mostrato nella pagina Impostazioni → Identità.
# Python example using PyJWT
import jwt, os, time
token = jwt.encode(
{
"sub": user.id,
"email": user.email,
"name": user.name,
"phonenumber": user.phone,
"custom_attributes": {"plan": user.plan},
"aud": "agentkit:chatbot:YOUR_CHATBOT_ID",
"iat": int(time.time()),
"exp": int(time.time()) + 3600,
},
os.environ["AGENTKIT_CHATBOT_IDENTITY_SECRET"],
algorithm="HS256",
)
Passare il token al widget
Imposta il token prima che lo script del widget si carichi (per esempio, iniettalo lato server nella pagina):
<script>
window.agentkitUserConfig = { token: 'YOUR_SIGNED_TOKEN' };
</script>
Nelle single-page app, aggiorna o azzera l'identità a runtime — per esempio dopo un login o un logout:
// After the user logs in (or the token is refreshed):
window.agentkit('identify', { token: newToken });
// After the user logs out:
window.agentkit('resetUser');
Il widget allega il token a ogni richiesta di chat automaticamente; non devi impostare tu alcun header.
Privacy
I campi del profilo verificati (email, name, phonenumber, custom_attributes) vengono salvati sul Contatto solo lato server. Non vengono mai inseriti nel prompt dell'agente o nel contesto RAG, e non vengono mai restituiti da alcun endpoint pubblico. L'agente non "vede" con chi sta parlando.
Comportamento della verifica
La verifica non blocca mai una chat. Il visitatore può sempre parlare con l'agente; l'unica differenza è se viene collegato o meno un Contatto.
| Situazione | Risultato |
|---|---|
| Nessun token | Visitatore anonimo. Nessun Contatto collegato. (Non è un errore.) |
| Token valido | Verificato. Contatto creato/aggiornato e collegato alla conversazione. |
| Firma non valida / token malformato | Anonimo. Errore registrato nei log. |
| Token scaduto | Anonimo. Errore registrato nei log. |
aud non corrisponde a questo agente | Anonimo. Errore registrato nei log. |
| I claim del profilo superano i limiti | Anonimo. Errore registrato nei log. |
Gli altri controlli di accesso restano validi
La verifica dell'identità è indipendente da chi può caricare il widget. Le impostazioni di restrizioni di dominio e visibilità continuano ad applicarsi separatamente.