Vérification d'identité
Votre write key publique identifie votre projet, mais elle n’authentifie personne : n’importe qui peut ouvrir une console de navigateur et envoyer des événements avec distinct_id: "[email protected]". La vérification d’identité ferme cette brèche — votre backend signe un JWT à courte durée de vie prouvant que ce navigateur est bien cet utilisateur, et Kilden le vérifie sur chaque événement identifié.
Le trafic anonyme n’est pas concerné : il n’y a aucune identité à forger, donc les événements anonymes n’ont jamais besoin de token.
Fonctionnement
Section intitulée « Fonctionnement »- Dans les réglages du projet, vous créez un secret d’identité (distinct de vos write keys). Chaque secret a un
kid(key id), et plusieurs peuvent être actifs en même temps, si bien que la rotation se fait sans fenêtre de bascule. - À la connexion, votre backend signe un JWT avec ce secret — HS256, avec l’id utilisateur dans
sub. - Le SDK envoie le token avec chaque batch d’événements dans
Authorization: Bearer <token>. - Le pipeline le vérifie : signature contre un
kidactif,expvalide, etsubégal audistinct_idde l’événement. Le résultat est stocké sur chaque événement dansverified.
Le token
Section intitulée « Le token »Payload des claims :
{ "sub": "user_4821", "iat": 1752192000, "exp": 1752195600, "traits": { "plan": "pro" }}sub— obligatoire. Doit être égal audistinct_idque le navigateur utilisera (ce que vous passez àidentify()).exp— obligatoire. Gardez-le court (de quelques minutes à quelques heures) ; le SDK le rafraîchit automatiquement.kid— obligatoire, dans le header du JWT (pas dans le payload). Identifie le secret d’identité du projet qui a signé le token.traits— optionnel. Traits signés, appliqués comme vérifiés côté serveur.- Algorithme : HS256 uniquement. Les tokens signés avec autre chose (y compris
none) échouent à la vérification.
Signer dans votre backend
Section intitulée « Signer dans votre backend »import jwt from 'jsonwebtoken';
// Depuis les réglages du projet → Vérification d'identité.// Le secret ne quitte jamais votre 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, // doit correspondre à l'id passé à 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;
// Depuis les réglages du projet → Vérification d'identité.$secret = getenv('KILDEN_IDENTITY_SECRET');$kid = getenv('KILDEN_IDENTITY_KID');
function kildenIdentityToken(string $userId, array $traits = []): string{ $now = time();
$payload = [ 'sub' => $userId, // doit correspondre à l'id passé à kilden.identify() 'iat' => $now, 'exp' => $now + 3600, 'traits' => (object) $traits, ];
return JWT::encode($payload, $GLOBALS['secret'], 'HS256', $GLOBALS['kid']);}(Utilise firebase/php-jwt ; le quatrième argument définit le header kid.)
Brancher le SDK
Section intitulée « Brancher le SDK »Laissez le SDK gérer le cycle de vie du token — il le rafraîchit environ une minute avant exp et réessaie une fois sur un 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; },});
// après la connexion :kilden.identify('user_4821');Alternatives : passer un token que vous avez déjà à l’init (identityToken: '...'), par appel (identify(id, traits, { token })), ou impérativement (setIdentityToken(token)). À la déconnexion, reset() l’efface.
Le token voyage par batch, dans le header Authorization: Bearer. Une exception documentée : le flush de fin de page peut se rabattre sur sendBeacon, qui ne peut pas transporter de headers, donc le token part dans le corps comme identity_token — même protection TLS, vérifié en second.
Modes d’application
Section intitulée « Modes d’application »La vérification est toujours calculée — chaque événement identifié reçoit verified: true/false, quel que soit le mode. Le mode ne gouverne que le sort des mutations d’identité non vérifiées ($identify, $set, $set_once) :
| Mode | Mutations d’identité non vérifiées d’utilisateurs identifiés |
|---|---|
off |
Appliquées normalement |
monitor |
Appliquées normalement, mais chacune est comptée pour que vous voyiez exactement ce que enforce bloquerait |
enforce |
Non appliquées : elles ne peuvent ni créer de personnes, ni lier des identités, ni écrire des traits. La résolution d’identité des événements identifiés non vérifiés devient une simple consultation — les mappings existants attribuent toujours, mais rien de nouveau n’est créé |
Comme monitor mesure précisément ce que enforce bloquerait, le déploiement sûr est : instrumenter le token → regarder le compteur d’événements non vérifiés tomber à zéro → passer en enforce. La bascule ne change aucune donnée, seulement le comportement.
Deux règles tiennent dans tous les modes :
- Les événements ne sont jamais jetés. Une vérification en échec conserve l’événement avec
verified: false; il est exclu des consommateurs sensibles à la confiance (déclencheurs de campagne, et les lectures du messenger quand la messagerie sur canaux identifiés sera livrée), mais reste dans vos analytics. - Les événements anonymes passent toujours. Leur
verified: falseest une convention (il n’y a rien à vérifier), pas de la méfiance. Les événements côté serveur envoyés avec une clé secrète sontverified: true— la clé secrète est l’authentification.
Traits signés
Section intitulée « Traits signés »Les traits inclus dans le JWT sont appliqués comme un $set vérifié côté serveur et priment sur les traits non signés du même événement. Utilisez-les pour les valeurs que le navigateur ne devrait pas pouvoir revendiquer sur lui-même (plan, rôle, statut du compte). Pour les faits qui pilotent de l’argent ou de la messagerie, préférez envoyer l’événement lui-même côté serveur.
Rotation
Section intitulée « Rotation »Créez un nouveau secret (nouveau kid) dans les réglages du projet, déployez votre backend en signant avec, puis désactivez l’ancien kid. Plusieurs secrets actifs signifient une rotation sans interruption ; les tokens signés par un kid désactivé échouent immédiatement à la vérification.