Поля токена
Полный справочник claim'ов JWT зрителя, полей билета сессии и директив внутренних принципалов — с типами, умолчаниями и поведением при отсутствии.
Эта страница — справочник. Настраиваемых артефактов три, и они не взаимозаменяемы.
| Артефакт | Кто выпускает | Чем подписан | Где описан |
|---|---|---|---|
| JWT зрителя | ваш внешний код | auth_backend.secret (HS256) или ваш приватный ключ (JWKS) |
§ ниже |
| Статический принципал | конфигурация | не подписан — это строка из файла | § ниже |
Билет сессии ?ssid= |
сам сервер | ключ из session_keys |
§ ниже, поля не настраиваются |
Ещё два артефакта существуют, но снаружи не настраиваются вовсе: короткоживущий медиа-грант панели
управления (срок жёстко 300 секунд) и токен администратора для /api/v1 (срок 12 часов) — см.
Доступ к админке и API.
Ни эндпоинта /api/v1, ни кнопки в панели: токены зрителей выпускает исключительно ваш код. Готовые
скрипты — Генераторы токенов на Python.
JWT зрителя: заголовок#
| Поле | Тип | Обяз. | Поведение |
|---|---|---|---|
alg |
строка | да | Для type hs256 — ровно HS256, регистрозависимо. Для type jwks — RS256 или ES256, причём алгоритм привязан к типу ключа: RS256 проверяется только ключом RSA, ES256 — только EC. Любое другое значение, включая none, → 401 |
typ |
строка | нет | не проверяется |
kid |
строка | нет | только для jwks: указывает, каким ключом набора проверять. Без kid перебираются все ключи подходящего алгоритма. Неизвестный kid → отказ и досрочное обновление набора ключей |
JWT зрителя: полезная нагрузка#
Обязателен по существу только claim с правами — без него ни один путь не откроется. Все остальные поля необязательны, и у каждого есть смысл «если не передать».
| Claim | Тип | Если не передать | Поведение |
|---|---|---|---|
grants (имя задаётся perms_claim) |
массив | прав нет → любой путь 403 |
Массив смешанный: элемент-объект — обычное разрешение, элемент-строка — компактный грант. Можно передать и как JSON-строку: "grants":"[{…}]" разворачивается |
sub |
строка | сессия без субъекта | попадает в учёт сессии; сворачивается в билет |
exp |
число, unix-секунды | токен бессрочен | отказ при exp <= now, тело token expired. Допуска на расхождение часов нет — токен отвергается ровно в секунду exp |
nbf |
— | — | не поддерживается: токен «из будущего» принимается как обычный |
iat |
число | — | принимается, не проверяется |
iss |
строка | если auth_backend.issuer задан — 401 |
точное сравнение, и только когда issuer настроен на сервере |
aud |
строка или массив строк | если auth_backend.audience задан — 401 |
массив трактуется как «любой из» |
ip |
строка IPv4/IPv6 | не привязан к адресу | запрос с другого адреса → 403. Неверный формат адреса → 401 |
net |
массив CIDR, не более 32 | не привязан к сети | запрос вне всех сетей → 403. Более 32 элементов → 403, некорректный CIDR → 401 |
proto |
массив протоколов, не более 8 | токен годен для любого протокола | сужает токен целиком. Значения: hls, dash, mse-ws, http-ts, rtsp, rtmp, whep, whip, api. Проверяется первым, раньше прав |
ref |
массив host-шаблонов | замка нет | замок Referer на уровне токена: Origin/Referer запроса обязан совпасть, правила те же, что у allowed_referers |
jti |
строка | отзыв невозможен | работает только с type jwks и заданным auth_backend.revoked_url: токен, чей jti в списке, получает 403 |
hcc |
число | ограничения нет | наследие: если hcc есть, а proto пуст, токен автоматически сужается до hls + mse-ws. Проверено: DASH таким токеном → 403 |
ps |
булево | обычный токен | не задавайте на этом сервере — см. предупреждение ниже |
proto помещается восемьОграничение «не более 8» действует только на общетокенный claim proto: перечислить в нём все
девять значений нельзя, ответ будет 403. «Все протоколы» задаются не перечислением, а
отсутствием поля.
На поле protocols внутри отдельного разрешения этот предел не распространяется — проверено, все
девять значений принимаются (200).
| Что | 8 значений | 9 значений |
|---|---|---|
proto — на весь токен |
200 |
403 |
protocols — внутри разрешения |
200 |
200 |
rtmp в списке протоколов закрывает и RTMPЗначение rtmp в этом словаре появилось вместе с закрытием RTMP, и трактуется оно в обе стороны:
токен, сужённый до ["hls"], не пустит ни RTMP-зрителя, ни RTMP-публикатора. Проверьте
выданные ранее токены, если через RTMP у вас кто-то работает.
ps: true ломает сессию после первого запросаПлейлист с таким токеном отдаётся (200), но любой следующий запрос по выданному билету
возвращает 403 — плеер получит манифест и тут же встанет. Проверено на стенде. Поле не имеет
на медиасервере ни одного сценария применения; просто не включайте его.
exp не истекает никогдаПоле необязательное, и без него срок не проверяется вовсе (проверено: 200). Отозвать такой токен
можно только сменой секрета подписи — то есть разом отозвав все токены. Всегда ставьте exp.
Элемент массива прав: объект#
{"action":"read","path":"cam","labels":["site-north"],"protocols":["hls","mse-ws"]}
| Поле | Тип | Обяз. | Смысл |
|---|---|---|---|
action |
read · playback · publish · api · manage · metrics |
да | неизвестное значение отвергает весь токен |
path |
строка | нет* | точный путь потока без ведущего /; *-глоб (live/*); * = все потоки |
labels |
массив строк | нет* | точное строковое совпадение с меткой потока |
protocols |
массив | нет | пусто или отсутствует = все протоколы |
* Нужно хотя бы одно из path / labels. Разрешение без обоих не открывает ничего:
{"action":"read"} → 403 (проверено). «Все потоки» пишется явно: {"action":"read","path":"*"}.
Схема строгая: незнакомое поле — ошибка, а не «лишнее, пропустим». Написали protocol вместо
protocols — получите 403 на всё, включая остальные, правильно оформленные разрешения (проверено).
Элемент массива прав: строка (компактный грант)#
<метка-b64u22>.<маска-hex> либо *.<маска-hex> — выдаёт биты привилегий, а не действия.
Подробно, с таблицей масок и примерами, — Метки потоков.
Некорректная строка молча отбрасывается: токен остаётся валидным, но это право не считается.
Билет сессии ?ssid=#
Поля самого билета не настраиваются — он выпускается сервером. Настраивается его политика:
session_keys { ttl 3600; vod_session_ttl 86400; bind_ip off; secret "общий-секрет-подписи-билетов"; }
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
ttl |
целое, секунды, > 0 | 3600 |
горячее |
vod_session_ttl |
целое, секунды, 300…604800 |
86400 |
горячее |
bind_ip |
флаг on / off; голое bind_ip; = on |
off |
горячее |
secret |
строка, непустая | пусто | горячее |
ttl— срок жизни билета. Продлевается скользяще, пока плеер опрашивает плейлист, но никогда не дольше, чемexpгранта, которым билет был выпущен.vod_session_ttl— потолок продолжения сессии видео по запросу. Значение вне диапазона — ошибка конфигурации:session_keys.vod_session_ttl must be 300..=604800 seconds; got N.bind_ip— вносит адрес клиента в подпись билета. Мобильный клиент, сменивший сеть, получит403и переустановит сессию.secret— если пусто, ключ выводится изauth.session_secret; если и его нет, генерируется случайный секрет на эту загрузку (билеты не переживут перезапуск). Смена значения немедленно обесценивает все выданные билеты.
Ярус билетов включается автоматически вместе с любым режимом auth_backend и отключить его
нельзя.
Из чего состоит билет#
Ничего из перечисленного не настраивается, но знать состав полезно при диагностике: билет несёт
номер эпохи ключа, одноразовый идентификатор сессии, срок, код протокола, снимок маски привилегий и
подпись. В подпись дополнительно входят — но не хранятся в самом билете — путь потока, хеш
User-Agent и адрес клиента (если включён bind_ip). Поэтому билет непереносим между потоками,
браузерами, протоколами и классами привилегий.
Внутренние принципалы (type internal)#
principal alice { pass hunter2; permission read cam hls; permission playback dvr/cam1 hls rtsp; permission read label=north label=vip; }
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
principal <имя> |
имя блока; any = совпадает с любым запросом |
— | горячее |
pass |
строка либо sha256:<hex> |
не задан | горячее |
token |
строка | не задан | горячее |
permission |
<действие> [<путь>] [label=<метка>]… [<протокол>]… — повторяемая |
— | горячее |
Правила разбора строки permission: первый токен — действие; следующий считается путём, если
он не начинается с label=; все оставшиеся label= — метки, всё прочее — протоколы. Путь и метки
складываются по ИЛИ.
Принципалу нужен либо token, либо пара имя + pass, либо имя any; иначе конфигурация не
пройдёт проверку: principal #0: needs a `token`, or a `user`+`pass`, or `user any` .
Ни у пароля, ни у токена принципала нет exp. Отозвать доступ можно только правкой конфигурации.
Для временных ссылок используйте hs256 или jwks.
Контракт ответа внешней службы (type http)#
Здесь токен придумываете вы — сервер лишь пробрасывает предъявленное клиентом как есть. Настраивается не токен, а ответ вашей службы:
| Поле ответа | Тип | Смысл |
|---|---|---|
sub |
строка | субъект для учёта сессии |
permissions |
массив тех же объектов, что в разделе выше | заменить набор прав (уточнение гранта) |
ttl_secs |
число | становится сроком жизни выпускаемого билета — то есть ваша служба управляет частотой повторных обращений |
Схема строгая: неизвестное поле внутри permissions отвергает весь ответ. Пустое тело с кодом
2xx означает «разрешить ровно запрошенную пару действие + путь».
Что настроить нельзя#
| Что | Значение | Почему это важно знать |
|---|---|---|
| Срок медиа-гранта панели управления | 300 секунд, жёстко | панель перевыпускает грант сама; в сторонний плеер такой токен не отдают |
Срок токена администратора /api/v1 |
12 часов | получается заново через POST /api/v1/auth/login |
| Таймаут вызова внешней службы авторизации | константа | ключа timeout в грамматике auth_backend { } нет |
Допуск на расхождение часов при проверке exp |
отсутствует | выпускайте токены с запасом и синхронизируйте время по NTP |
| Правила авторизации по геолокации | нет такого механизма | ограничивайте адреса через ip / net в токене |