Skip to content

JWT и сервисные учетные записи

VideoGrace Server может выпускать стандартные bearer JWT для браузерных клиентов, REST API, media/blob каналов и сервисных worker'ов. JWT-flow нужен для PWA, внешних сервисов, транскрибера, recorder/consolidator pipeline и будущих интеграций без передачи пользовательских паролей.

Включение JWT

Задайте общий серверный secret:

[Auth]
JwtSecret = <длинный_случайный_секрет>
JwtTtlSec = 604800
RefreshTtlSec = 2592000

Эквивалентные переменные окружения:

VG_JWT_SECRET=<длинный_случайный_секрет>
VG_JWT_TTL_SEC=604800
VG_REFRESH_TTL_SEC=2592000

Параметры:

Параметр Назначение
JwtSecret / VG_JWT_SECRET Секрет HMAC-SHA256 для подписи access JWT.
JwtTtlSec / VG_JWT_TTL_SEC Время жизни access token, по умолчанию 7 дней.
RefreshTtlSec / VG_REFRESH_TTL_SEC Время жизни refresh token, по умолчанию 30 дней.

Если secret не задан, сервер может работать с legacy opaque token. Для production и сервисной авторизации задайте JWT-secret обязательно.

Что хранится в БД

Начиная с версии БД 3.0.260531 сервер создает таблицы:

Таблица Назначение
refresh_tokens HMAC-хеши refresh token, client_id, время выпуска и истечения.
jwt_revoked Отозванные jti access JWT до окончания их TTL.
service_accounts Привязка имени сервиса к обычному пользователю VideoGrace.

Access JWT не хранится в БД. Refresh token хранится только в виде хеша.

Обновление access token

Клиент получает refresh_token при первичном входе и затем может запросить новый access token:

POST /api/v1.0?auth_refresh
Content-Type: application/json

{
  "refresh_token": "..."
}

Ответ:

{
  "result": 200,
  "access_token": "...",
  "token_type": "Bearer"
}

Refresh token нельзя использовать как bearer token для REST, media, blob или CAN.

Отзыв токенов

Точечный отзыв access JWT выполняется через jti:

insert into jwt_revoked (jti, expires_at, created_at, reason)
values ('<jwt_jti>', <jwt_exp>, strftime('%s','now'), 'admin revoke');

Чтобы сбросить все access JWT, смените JwtSecret и перезапустите сервер. Это разлогинит активные JWT-сессии, поэтому выполняйте операцию в окно обслуживания.

Чтобы отозвать refresh token конкретного пользователя:

delete from refresh_tokens
where client_id = <client_id>;

Service account для Transcriber

Создайте отдельного пользователя, например transcriber, и выдайте ему только нужные права. После этого добавьте сервисную учетную запись:

insert into service_accounts
  (name, client_id, scopes, enabled, created_at)
values
  ('transcriber', <client_id>, '["conference:join","media:render","chat:write"]', 1, strftime('%s','now'));

При постановке CAN job transcriber.start без payload.auth сервер:

  1. Находит service_accounts.name = 'transcriber' или имя из payload.service_account.
  2. Проверяет, что запись включена и не истекла.
  3. Выпускает короткий access JWT для связанного пользователя.
  4. Добавляет токен в payload.auth.
  5. Отправляет задание online worker'у role=transcriber.

Пример CAN job:

{
  "job_type": "transcriber.start",
  "target_role": "transcriber",
  "required_capability": "speech_to_text",
  "payload": {
    "server_url": "https://join.videograce.ru",
    "conference_tag": "teamsink",
    "source": {
      "type": "conference_audio"
    },
    "language": "ru",
    "window_sec": 4
  }
}

Пароль сервисного пользователя в CAN job передавать не нужно.

Эксплуатационные рекомендации

  • Храните JwtSecret и VG_CAN_SERVICE_TOKEN как разные секреты.
  • Не используйте учетную запись owner/admin для сервисов транскрибации и записи.
  • Для каждого класса сервисов создавайте отдельную service account.
  • После изменения JwtSecret перезапустите сервер и проверьте повторный вход web/PWA клиентов.
  • Для резервного копирования сохраняйте основную БД: без нее refresh token и service account state будут потеряны.