Выпуск токенов на вашем бэкенде
Поддерживаемый способ выдать токен входа — и одно поле, потеря которого молча отключает контроль одной сессии.
Почему на бэкенде?
Серверный секрет никогда не попадает в приложение. Любой ключ, вшитый в APK, можно извлечь и выдать себя за любого пользователя.
Передавайте данные устройства
Ваш сервер не видит устройство. Приложение отправляет эти значения вашему серверу, а он передаёт их в том же запросе.
Сбой происходит молча
Без device_id проверка «один аккаунт — одно устройство» выходит раньше: ни ошибки, ни лога. Токен выдаётся, защита просто выключена.
Измерено, а не предположено
За три часа реальных входов: токены с бэкенда — 3 224 входа, 100 % без идентификатора устройства. Токены из кита — 1 641 вход, 0 %.
Поля запроса токена
POST на /api/v1/token с серверным секретом в заголовке.
| Поле | Уровень | Значение |
|---|---|---|
user_idstring | Обязательно | Who the token is for. Your own user id. (Previously `identity` — still accepted.) |
room_idstring | Обязательно | Which room they are joining. (Previously `room_name` — still accepted.) |
device_idstring | Рекомендуется | A stable id for the PHYSICAL DEVICE — not the user, and not the session. This is what enforces one account on one device: when the same user_id joins from a different device_id, the previous device is messaged and removed. Omit it and that enforcement silently does nothing: the check returns early, logs nothing, and the old device stays signed in. |
device_modelstring | Рекомендуется | e.g. SM-A175F. Feeds per-handset quality analysis — which models have audio or video trouble. |
osstring | Рекомендуется | android | ios. |
os_versionstring | Рекомендуется | e.g. 14. |
app_versionstring | Рекомендуется | Your app's version, so a regression can be traced to a release. |
display_namestring | Необязательно | Shown to other participants. Omit it and the name stays empty — we never substitute the user id for it. |
rolestring | Необязательно | Only honoured from a server-signed request, and only while your project still carries the client-asserted-role exception. The supported path is PUT /rooms/:room/participants/:id/role. |
typestring | Необязательно | audio_room | live_stream. Legacy kits send `service` (+ `kind`) instead and the type is derived. |
На вашем сервере
Секрет живёт только здесь. Отмеченные поля приходят из приложения — сервер не может знать их сам.
// Your backend — the app never sees the server secret.
const res = await fetch("https://engine.udt-stream.com/api/v1/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-App-Secret": process.env.UTD_SERVER_SECRET, // never ship this in the app
},
body: JSON.stringify({
user_id: currentUser.id,
room_id: roomId,
// 🔴 Forwarded FROM THE APP. Your server cannot know these on its own,
// and without device_id one-account-one-device stops working for your users.
device_id: body.device_id,
device_model: body.device_model,
os: body.os,
os_version: body.os_version,
app_version: body.app_version,
}),
});В вашем приложении
Отправьте данные устройства на собственный бэкенд, он передаст их дальше. Идентификатор должен быть стабильным между перезапусками.
// Your app — send the device facts to YOUR backend, which forwards them to us.
final deviceId = await MyDeviceIdentity.stableId(); // persisted, survives app restarts
await myApi.post("/rooms/$roomId/token", body: {
"device_id": deviceId,
"device_model": deviceInfo.model,
"os": Platform.isAndroid ? "android" : "ios",
"os_version": deviceInfo.version,
"app_version": packageInfo.version,
});Коды отказа (403)
Каждый отказ несёт code. Читайте код — сообщение «вас удалили» уместно только для первого.
| Код | Значение | Что делать |
|---|---|---|
user_banned | This user is banned from this room. | Show them they were removed. This is the ONLY code that should produce that message. |
room_type_disabled | The project does not have this room type enabled. | A configuration problem, not a user problem. Never show a removal notice. |
streaming_disabled | The streaming service is not enabled for this project. | Same — configuration, not the user. |
appkey_identity_mint_disabled | You tried to mint an identity-bearing token with the publishable app_key. | Mint from your backend with the server secret instead. This is the path this page describes. |
Режимы аутентификации
Движок записывает режим при каждом входе, чтобы вы могли проверить, на каком пути вы действительно находитесь.
secret / signature / bearerYour backend, authenticated with your server secret. The recommended path.
app_keyThe device, using the publishable app key. The legacy path — being closed.
Готовы создавать вместе с UTD?
Создайте аккаунт, пополните главный кошелёк и включите нужные вам сервисы.