Identity verification: user_hash and the company signature
Introduce the signed-in user and their company to the widget with proof: user_hash is computed on the server and the company id is part of the signature; widget, Node.js, Go, PHP and curl samples.
user_hash is the only way to introduce a signed-in user to the widget with proof:
# user that belongs to a company (identify sends company.id): both ids are signed together
user_hash = hex(HMAC-SHA256(widget_identity_secret, user_id + "\n" + company_id))
# no company: the user id alone
user_hash = hex(HMAC-SHA256(widget_identity_secret, user_id))user_id is the user's id in your system and is the external id of the next section; company_id is the company's id in your system and goes to identify as company: { id }. The value is computed on your server only; your site and your mobile app receive the finished user_hash, never the secret. A contact verified with a valid user_hash gets the Verified badge in the panel and their anonymous history moves to the same contact. When the company id is signed, the contact is bound to that company by the signed value, the company gets the Verified badge in the panel too, and a verified user cannot claim another company; the identify event reports company_verified: true. When identify is rejected the widget keeps working but the user stays anonymous, and the error event carries WIDGET_IDENTITY_DISABLED (no secret generated yet) or WIDGET_IDENTITY_INVALID (mismatch, including a hash that signs another company id). Neither id may contain a line break (\n).
Migration. The original user_hash over user_id alone keeps working (backward compatible). When such a call also carries company.id, the user is still verified but the company id is not linked and not stored: company.name and company.domain are used only as matching hints, the widget prints a fixed console warning and the identify event reports company_verified: false. To bind the company by its id, add company_id to the signature on your server: Node identityHash(secret, userId, companyId), Go IdentityCompanyHash(secret, userID, companyID); the PHP and Laravel helpers get the same formula in their own releases.
// Adım 1: sunucunuzdan aldığınız user_hash ile giriş yapmış kullanıcıyı tanıtın.
// @ts-check
ClickFix("boot", { widgetId: "WIDGET_ID", locale: "tr" });
fetch("/api/support-session") // sizin ucunuz: { user_id, user_hash, company_id } döner
.then((r) => r.json())
.then((session) =>
ClickFix("identify", {
user_id: session.user_id, // kişinin dış kimliği
// Firma ile: hex(HMAC-SHA256(anahtar, user_id + "\n" + company_id)), sunucuda.
// Firmasız: hex(HMAC-SHA256(anahtar, user_id)).
user_hash: session.user_hash,
name: "Ayşe Yılmaz",
email: "ayse@example.com",
company: { id: session.company_id }, // imzadaki firma kimliği
}),
);
ClickFix("on", "error", (e) => {
if (e.code === "WIDGET_IDENTITY_INVALID")
console.warn("user_hash eşleşmedi:", e.message);
});// Adım 1: user_hash sunucuda hesaplanır ve giriş yapmış kullanıcıya verilir.
import { identityHash } from "@getclickfix/node";
// Panel > Web widget > Güvenlik > Kimlik doğrulama anahtarı (bir kez gösterilir)
const secret = process.env.CLICKFIX_IDENTITY_SECRET!;
// Oturum açmış kullanıcının sizin sisteminizdeki kimliği (dış kimlik) ve
// firmasının kimliği (identify'daki company.id). Firma verilirse imza ikisini
// birden kapsar: hex(HMAC-SHA256(anahtar, user_id + "\n" + company_id)).
export function userHashFor(userId: string, companyId?: string): string {
return identityHash(secret, userId, companyId);
}
// Örnek: /api/support-session uç noktanız bunu döner, tarayıcı identify'a verir
console.log(
JSON.stringify({
user_id: "1001",
user_hash: userHashFor("1001"), // firmasız: eski formül
company_id: "F-77",
company_user_hash: userHashFor("1001", "F-77"), // company: { id: "F-77" } ile gönderilir
}),
);package main
import (
"context"
"encoding/json"
"os"
clickfix "github.com/ClickSolveMainTR/clickfix-sdks/go"
)
// Adım 1: user_hash sunucuda hesaplanır; anahtar tarayıcıya ve uygulamaya gitmez.
func userHash(ctx context.Context) error {
secret := os.Getenv("CLICKFIX_IDENTITY_SECRET") // Panel > Web widget > Güvenlik
userID := "1001" // kullanıcının sizin sisteminizdeki kimliği
companyID := "F-77" // firmasının kimliği (identify: company.id)
return json.NewEncoder(os.Stdout).Encode(map[string]string{
"user_id": userID,
"user_hash": clickfix.IdentityHash(secret, userID), // firmasız: eski formül
// Firma ile: imza user_id + "\n" + company_id üzerinden; company: { id } ile gönderilir.
"company_id": companyID,
"company_user_hash": clickfix.IdentityCompanyHash(secret, userID, companyID),
})
}<?php
// Adım 1: user_hash sunucuda hesaplanır ve giriş yapmış kullanıcıya verilir.
require __DIR__.'/vendor/autoload.php'; // composer require clickfix/sdk
use ClickFix\UserHash;
// Panel > Web widget > Güvenlik > Kimlik doğrulama anahtarı (bir kez gösterilir)
$secret = getenv('CLICKFIX_IDENTITY_SECRET');
// Oturum açmış kullanıcının sizin sisteminizdeki kimliği (dış kimlik)
function userHashFor(string $secret, string $userId): string
{
return UserHash::make($secret, $userId);
}
// Örnek: /api/support-session uç noktanız bunu döner, tarayıcı identify'a verir
echo json_encode(['user_id' => '1001', 'user_hash' => userHashFor($secret, '1001')]), PHP_EOL;# Adım 1: user_hash = hex(HMAC-SHA256(kimlik_anahtari, user_id)); yalnız sunucuda.
USER_ID="1001"
printf '%s' "$USER_ID" | openssl dgst -sha256 -hmac "$CLICKFIX_IDENTITY_SECRET" | sed 's/^.* //'
# Firma ile (company: { id }): imza user_id + "\n" + company_id üzerinden hesaplanır.
COMPANY_ID="F-77"
printf '%s\n%s' "$USER_ID" "$COMPANY_ID" | openssl dgst -sha256 -hmac "$CLICKFIX_IDENTITY_SECRET" | sed 's/^.* //'If you Rotate the secret, values made with the old one stop working; update the secret on your server at the same time. On sites that need cookie consent pass it with boot({ consent }) or ClickFix("consent", true); nothing is written to the browser before consent.
Last updated on