Pular para o conteúdo principal
DocumentaçãoIdentidade e sessões assinadas

Proteger a identidade do utilizador no SDK

Use um endpoint do backend do host para tokens de identidade do cliente de curta duração nas integrações web e nativas.

Nesta página

Os clientes retomam o seu contexto de suporte sem expor um signing secret ou support API token ao navegador ou ao bundle da app.

Mantenha a assinatura no backend

O seu backend autentica o cliente, assina um JWT DobroDesk de curta duração para a integração e devolve-o por um endpoint protegido pela sessão do host. A resposta para os wrappers móveis é JSON com uma string authorizationToken.

O SDK não cria este JWT e loadDobroDeskToken é uma função fornecida pelo host. Nunca inclua signing secret, support API token ou credenciais longas no JavaScript, bundle móvel ou repositório público.

O widget web suporta sessão anónima. Os SDKs nativos exigem identidade assinada antes de operações de rede e apresentação. Os pedidos nativos usam Authorization: Bearer... com x-dobrodesk-client: native-v1, sem Origin do navegador. Depois do início, o motor envia a prova como x-dobrodesk-session-token e o host não deve criar ou substituir esse cabeçalho.

Endpoint do host e fornecedores SDK
// 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(),
  }),
};

Configurar o signing secret e os claims

Em Admin > Channels > Website widgets, abra a integração do widget, defina o identity mode como Require a signed logged-in user e use Copy identity secret. Guarde o secret específico da integração juntamente com o Integration ID público no gestor de segredos do backend. O secret nunca deve ficar no navegador, no bundle móvel ou num repositório público. Use-o como chave de assinatura HS256.

Assine um JWT HS256 de três partes com typ JWT. Claims obrigatórios: iss = dobrodesk-widget:{integrationId}, aud = Integration ID público, sub = ID estável do cliente que não seja email, iat = segundos Unix atuais e exp no máximo 15 minutos depois de iat. O verificador aceita 60 segundos de desvio. Claims opcionais: name, email, email_verified: true e jti. Defina email_verified apenas depois de verificar o endereço.

Assinatura Web Crypto no servidor
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}`;
}

Associe e limpe a identidade deliberadamente

Use accountScope como identificador estável de cliente ou conta sem segredos. Ele isola a sessão nativa e a outbox. Não reutilize um scope para vários clientes.

Em Flutter, React Native, NativeScript ou Capacitor, chame logout antes de terminar a sessão ou mudar accountScope. Clientes iOS e Android diretos usam resetSession: reinicie o cliente e crie outro para a conta seguinte. Use resetSession quando o cliente descartar a conversa mas continuar ligado. Renovar o token não é trocar de conta.

Rejeite estados inseguros do token

  1. Rejeite token vazio, inválido, expirado ou de outro cliente no endpoint em vez de devolver uma credencial de suporte.
  2. Trate 401 ou session-expired como pedido de token novo para a mesma conta. Não troque accountScope nem crie sessão nova.
  3. Se logout ocorrer durante um pedido pendente, ignore o token tardio e isole a conta seguinte.