# Підтвердження особи користувачів, які увійшли

> Розпізнавайте користувачів, які увійшли, у чат-віджеті: ключ підтвердження, обчислення userHash на Node.js, PHP і Python, підтверджена пошта й вихід.

Якщо на вашому сайті чи в застосунку користувачі входять в обліковий запис, віджет може їх розпізнати. Тоді людина бачить свої розмови на будь-якому пристрої, а команда бачить один контакт замість кількох анонімних.

## Навіщо потрібен підпис

Браузеру довіряти не можна: будь-хто може викликати `identify` з чужою ел. поштою. Тому ваш сервер обчислює `userHash`, підпис HMAC-SHA256 із ключем підтвердження, якого браузер ніколи не бачить.

## Ключ підтвердження

Ключ є в налаштуваннях чат-віджета на вкладці «Підтвердження особи». Бачать і змінюють його лише власники.

- Тримайте ключ лише на сервері, наприклад у змінній `SUPPORT_IDENTITY_SECRET`. Ніколи не вставляйте його в код браузера.
- Після створення нового ключа старий працює ще 24 години, щоб ви встигли оновити сервер.

![Налаштування підтвердження особи з прихованим ключем](https://hrc.lt/screens/uk/project-identity.desktop.1600.80022661.webp)

## Що підписувати

Підпис обчислюється з рядка `v1:<ID>:<ел. пошта>`. Ел. пошта без пробілів на краях і малими літерами; відсутня частина залишається порожньою.

```text
v1:<externalId>:<ел. пошта без пробілів по краях, малими літерами>

v1:12345:jonas@example.com   ID і ел. пошта
v1:12345:                    лише ID
v1::jonas@example.com        лише ел. пошта, потрібне налаштування
                             «Мій застосунок перевіряє адреси ел. пошти»
```

`userHash` це HMAC-SHA256 цього рядка з ключем підтвердження, записаний 64 шістнадцятковими символами.

## Код для сервера

Node.js:

```js
// Node.js (Express): ваш endpoint, лише для користувача після входу
import { createHmac } from 'node:crypto';

app.get('/api/support-hash', requireLogin, (req, res) => {
  const user = req.user;
  const email = (user.email ?? '').trim().toLowerCase();
  const canonical = `v1:${user.id ?? ''}:${email}`;
  const userHash = createHmac('sha256', process.env.SUPPORT_IDENTITY_SECRET)
    .update(canonical)
    .digest('hex');
  res.json({ userHash });
});
```

PHP:

```php
<?php
// PHP: mb_strtolower, не strtolower, щоб Ї та Ж теж стали малими
$email = mb_strtolower(trim($user->email ?? ''), 'UTF-8');
$canonical = 'v1:' . ($user->id ?? '') . ':' . $email;
$secret = getenv('SUPPORT_IDENTITY_SECRET');
$userHash = hash_hmac('sha256', $canonical, $secret);
```

Python:

```python
# Python
import hashlib
import hmac
import os

user_id = "" if user.id is None else str(user.id)
email = (user.email or "").strip().lower()
canonical = f"v1:{user_id}:{email}"
secret = os.environ["SUPPORT_IDENTITY_SECRET"].encode()
user_hash = hmac.new(secret, canonical.encode(), hashlib.sha256).hexdigest()
```

## Код для браузера

Завжди передавайте `externalId` рядком: число ігнорується.

```js
// У браузері: отримайте підпис користувача від свого сервера
const { userHash } = await fetch('/api/support-hash', {
  credentials: 'include',
}).then((r) => r.json());
HrcWidget('identify', {
  externalId: String(user.id ?? ''),
  email: user.email,
  name: user.name,
  userHash,
});

// При виході
HrcWidget('reset');
```

З `identify` можна передати й поля профілю, дивіться [Профіль відвідувача](https://hrc.lt/uk/docs/widget/visitor-profile).

## «Мій застосунок перевіряє адреси ел. пошти»

Вмикайте, лише якщо ваш застосунок перевіряє, що ел. пошта належить користувачу (надсилає код або посилання). Тоді підписана ел. пошта об'єднує листи й розмови однієї людини в один контакт в усіх чат-віджетах і поштових скриньках.

Доки цей параметр вимкнено, завжди передавайте `externalId` користувача. Підписану ел. пошту без ID відхиляють із помилкою `IDENTITY_INVALID`, а ел. пошта вважається не підтвердженою, доки людина не відповість на наш лист.

## Лише для тих, хто увійшов

Режим «Лише для тих, хто увійшов» дозволяє писати лише розпізнаним користувачам. Анонімна сесія не може надсилати повідомлення й змінювати профіль (`IDENTITY_REQUIRED`).

## Перевірте підпис

У налаштуваннях є поле для перевірки обчисленого значення: введіть ID, ел. пошту й значення з вашого сервера, і застосунок скаже, чи воно підходить. Перевірка виконується на сервері, ключ у браузер не надсилається. Якщо не підходить, перевірте, чи ел. пошта малими літерами і чи ви використовуєте ключ саме цього віджета.

Помилку ви бачите й на своєму сайті: `HrcWidget('on', 'identify-failed', ...)` отримує код, але ніколи сам підпис.

## Вихід

Коли користувач виходить, викличте `HrcWidget('reset')`. Віджет забуде сесію, і наступна людина на тому самому пристрої не побачить чужих розмов.
