Les clients peuvent reprendre leur contexte de support sans exposer le signing secret ni un support API token au navigateur ou au bundle de l'app.
Garder la signature sur votre backend
Votre backend authentifie le client actuel, signe un JWT d'identité client DobroDesk de courte durée pour l'intégration choisie et le renvoie depuis un endpoint protégé par la session de l'hôte. La réponse de l'endpoint utilisée par les wrappers mobiles est un JSON contenant une chaîne authorizationToken.
Le SDK ne crée pas ce JWT et loadDobroDeskToken n'est pas une fonction du SDK. Dans les exemples suivants, c'est une fonction fournie par l'hôte. N'incluez jamais le JWT signing secret, un DobroDesk support API token ou une credential de service longue durée dans le JavaScript navigateur, un bundle mobile ou un dépôt public.
Le widget web prend aussi en charge une session anonyme. Les intégrations natives exigent une identité client signée avant les opérations réseau et la présentation du widget. Les requêtes natives l'envoient comme Authorization: Bearer... avec x-dobrodesk-client: native-v1 et n'envoient pas d'Origin de navigateur. Après le démarrage de la session, le moteur natif gère la preuve de session reçue et l'envoie comme x-dobrodesk-session-token. L'hôte ne doit pas construire ni remplacer cet en-tête.
// This function belongs to your application. The route is your backend route.
async function loadDobroDeskToken(): Promise<string> {
const response = await fetch("/your-backend/dobrodesk-token", {
method: "POST",
credentials: "include",
headers: { Accept: "application/json" },
});
if (!response.ok) throw new Error("Customer token request failed");
const body = (await response.json()) as { authorizationToken?: unknown };
if (typeof body.authorizationToken !== "string" || !body.authorizationToken)
throw new Error("Customer token response is invalid");
return body.authorizationToken;
}
// Web can remain anonymous or apply the token after host login.
widget.setIdentityToken(await loadDobroDeskToken());
// React Native, NativeScript and Capacitor use the signed native shape.
const config = {
apiOrigin: "https://dobrodesk.com",
integrationId: "wgt_0123456789abcdef0123456789abcdef",
accountScope: currentCustomer.id,
credentialProvider: async () => ({
authorizationToken: await loadDobroDeskToken(),
}),
};Configurer le secret de signature et les claims
Dans Admin > Channels > Website widgets, ouvrez l'intégration du widget, définissez le mode d'identité sur Require a signed logged-in user et utilisez Copy identity secret. Stockez le secret propre à l'intégration avec l'Integration ID publique dans le gestionnaire de secrets de votre backend. Le secret ne doit jamais se trouver dans un navigateur, un bundle mobile ou un dépôt public. Utilisez-le comme clé de signature HS256.
Signez un JWT HS256 en trois parties avec typ JWT. Les claims obligatoires sont iss = dobrodesk-widget:{integrationId}, aud = l'Integration ID publique, sub = un identifiant client stable qui n'est pas une adresse e-mail, iat = les secondes Unix actuelles et exp au plus 15 minutes après iat. Le vérificateur accepte 60 secondes de décalage d'horloge. Les claims facultatifs sont name, email, email_verified: true et jti. Définissez email_verified uniquement après vérification de l'adresse par l'hôte.
const textEncoder = new TextEncoder();
const base64url = (bytes: Uint8Array) => {
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
};
// secretStore is your backend secret manager. Never run this in browser code.
export async function createDobroDeskIdentityToken(user: {
id: string;
email?: string;
emailVerified?: boolean;
name?: string;
}) {
const integrationId = await secretStore.get("DOBRODESK_WIDGET_ID");
const identitySecret = await secretStore.get("DOBRODESK_WIDGET_IDENTITY_SECRET");
const now = Math.floor(Date.now() / 1000);
const encode = (value: unknown) =>
base64url(textEncoder.encode(JSON.stringify(value)));
const header = encode({ alg: "HS256", typ: "JWT" });
const payload = encode({
iss: `dobrodesk-widget:${integrationId}`,
aud: integrationId,
sub: user.id,
iat: now,
exp: now + 5 * 60,
...(user.email
? {
email: user.email,
...(user.emailVerified === true ? { email_verified: true } : {}),
}
: {}),
...(user.name ? { name: user.name } : {}),
});
const key = await crypto.subtle.importKey(
"raw",
textEncoder.encode(identitySecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"],
);
const signature = base64url(
new Uint8Array(
await crypto.subtle.sign("HMAC", key, textEncoder.encode(`${header}.${payload}`)),
),
);
return `${header}.${payload}.${signature}`;
}Lier et effacer l'identité volontairement
Définissez accountScope comme un identifiant client ou compte stable de l'hôte, sans secret. Il isole l'état de session native durable et l'outbox. Ne réutilisez pas un même scope pour plusieurs clients connectés.
Avec Flutter, React Native, NativeScript ou Capacitor, appelez logout avant la fin de la session de l'hôte ou la modification de accountScope. Les clients iOS et Android directs exposent plutôt resetSession : réinitialisez ce client puis créez-en un nouveau pour le compte suivant. Appelez resetSession lorsque le client abandonne volontairement la conversation actuelle tout en restant connecté. Un renouvellement de token n'est pas un changement de compte et doit utiliser le même account scope.
Refuser les états de token dangereux
- Refusez dans l'endpoint de l'hôte un token vide, mal formé, expiré ou destiné au mauvais client au lieu de renvoyer une credential de support.
- Traitez une erreur SDK 401 ou session-expired comme une demande de nouveau token pour le même compte. Ne changez pas accountScope silencieusement et ne créez pas de nouvelle session.
- Si logout est demandé pendant une requête de token en attente, ignorez le token tardif et gardez le compte suivant isolé de la session précédente.