Skip to content

Токени і доступ ​

У сервері співіснують чотири незалежні механізми доступу. Плутанина між ними — найчастіша причина 401 під час написання клієнта.

Огляд ​

ТокенХто отримуєЧас життяНавіщо
artTokenбудь-який слухач1 годинаарти, аватари, тексти, ключ XOR
audioTokenслухач з artTokenкороткодоступ до аудіо
JWT адмінапісля входусесіяусі /api/admin/*
гостьовийзапрошений гістьсесіявхід у гостьову кімнату

artToken ​

Видається через сокет, не через HTTP: клієнт надсилає listener_init і отримує listener_uid з токеном усередині.

Токен прив'язаний до uid, який сервер виводить з IP-адреси з'єднання. Клієнт не може обрати собі ідентичність, і слухачі за спільним NAT отримають один uid на всіх.

Передається заголовком X-Art-Token або параметром ?token=.

audioToken ​

Обмінюється на artToken:

http
GET /api/audio-key
X-Art-Token:    <artToken>
X-Listener-Uid: <uid>

Відповідь містить expiresIn у секундах. Оновлюйте завчасно — референсний клієнт робить це за 30 секунд до кінця.

Ендпоінти аудіо вимагають обидва токени одночасно.

XOR-обгортка ​

Арти, аватари й тексти пісень віддаються не в чистому вигляді, а поксорені з ключем, що виводиться з artToken.

Ключ — це середній сегмент токена, закодований base64url:

js
export const xorDecrypt = (buf, token) => {
  const b64    = (token.split('.')[1] ?? '').replace(/-/g, '+').replace(/_/g, '/');
  const keyRaw = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
  const enc    = new Uint8Array(buf);
  const dec    = new Uint8Array(enc.length);
  for (let i = 0; i < enc.length; i++) dec[i] = enc[i] ^ keyRaw[i % keyRaw.length];
  return dec;
};

Аудіо цим не шифрується

Попри назву audioToken, самі аудіофайли не проходять через XOR. Токен там — лише перепустка, а байти віддаються як є. XOR стосується артів, аватарів і текстів, і ключем служить artToken.

Це обфускація, а не шифрування

Ключ видається клієнту на запит, а алгоритм відкритий. Такий захист відсіює випадкове вигрібання ресурсів чужими сторінками, але не є засобом безпеки й не має вважатися таким. Не покладайтеся на нього для чогось справді закритого.

JWT адміністратора ​

http
POST /api/admin/login
{ "login": "…", "password": "…" }

Далі Authorization: Bearer <token> до всіх /api/admin/*. Частина ендпоінтів додатково приймає токен у query — це зроблено для тегів <audio src>, де заголовок задати неможливо.

Понад JWT більшість адмінських ендпоінтів перевіряє ще й привілей — див. Привілеї.