HMAC — примеры на стэках
Виджет / HMAC examples

HMAC visitor token — примеры на популярных стэках

Готовые сниппеты эндпоинта /api/supporthub/token для FastAPI, Django, Flask, Express, Next.js API, Laravel, Rails, Go, .NET и Spring Boot. Полный референс с форматом payload, ротацией и edge-кейсами — в /docs/widget/hmac.

Что нужно сделать

  1. Получить workspace-секрет один раз и положить в env вашего бэкенда:
    http
    GET /api/v1/widget/signing-secret
    Authorization: Bearer sk_xxx
    
    200 OK
    { "secret": "wsig_..." }
  2. Реализовать у себя эндпоинт GET /api/supporthub/token по одному из шаблонов ниже. Эндпоинт должен:
    • аутентифицировать текущего пользователя (через session-cookie / JWT / что угодно);
    • взять стабильный user_id (PK из вашей БД, slug, и т.д.);
    • собрать payload {"user_id": "...", "exp": <unix>};
    • подписать raw JSON-байты через HMAC-SHA256;
    • вернуть { "token": "<base64url(payload)>.<hex(sig)>" }.
  3. Раскомментировать fetch-блок в установочном скрипте. Виджет автоматически передаст токен бэку SupportHub как data-visitor-token.

Примеры реализации

Все примеры используют HMAC-SHA256 поверх raw JSON-байт (не base64-строки), base64url-кодирование payload без padding-знака =, и компактный JSON без пробелов (separators=(",", ":") или эквивалент). TTL — 1 час; делайте по вкусу, но не вечно.

app/api/supporthub.pypython
import base64, hashlib, hmac, json, os, time
from fastapi import APIRouter, Depends, HTTPException

router = APIRouter()
SECRET = os.environ["SUPPORTHUB_SIGNING_SECRET"].encode()

@router.get("/api/supporthub/token")
async def supporthub_token(current_user = Depends(get_current_user)):
    if not current_user:
        raise HTTPException(401, "Unauthorized")

    payload = json.dumps(
        {"user_id": str(current_user.id), "exp": int(time.time()) + 3600},
        separators=(",", ":"),
    ).encode()
    sig = hmac.new(SECRET, payload, hashlib.sha256).hexdigest()
    payload_b64 = base64.urlsafe_b64encode(payload).rstrip(b"=").decode()
    return {"token": f"{payload_b64}.{sig}", "expires_in": 3600}

Тестовый прогон без бэкенда

Если хотите подёргать API руками до прикручивания эндпоинта — подпишите payload, например, в Python REPL и положите в HTML атрибутом data-visitor-token:

python
import base64, hashlib, hmac, json, time

SECRET = "wsig_..."   # ваш workspace-секрет
payload = json.dumps(
    {"user_id": "demo-42", "exp": int(time.time()) + 3600},
    separators=(",", ":"),
).encode()
sig = hmac.new(SECRET.encode(), payload, hashlib.sha256).hexdigest()
print(base64.urlsafe_b64encode(payload).rstrip(b"=").decode() + "." + sig)
html
<script async
        src="https://support.forestsnet.com/widget-bundle?ws=YOUR_WS"
        data-visitor-token="ВЫВОД_ИЗ_PYTHON_ВЫШЕ"></script>

Дальше

  • Полный референс HMAC — формат payload, валидация на бэке SupportHub, ротация секрета, edge-кейсы (просрочка, подмена, дрейф clock).
  • Identify посетителей — что отдавать в data-* рядом с токеном (имя, email, attrs).
  • Troubleshooting — почему 401 от SupportHub, почему виджет ушёл в anonymous fallback, как проверить подпись.
Была ли страница полезной?