Использование OIDC для провижнинга пользователей и авторизации¶
Agora позволяет интегрировать свою базу пользователей в корпоративный каталог по протоколу OIDC.
Локальная база данных пользователей отключается (это опционально и при желании можно её оставить) и становится полностью управляемой внешней системой (как правило центральной корпоративной системой, далее IdP (identity provider)). Права пользователя настраиваются во внешней системе, создание, блокировка и удаление пользователя происходит во внешней системе.
Важно: Agora не обращается к IdP при каждом API-запросе — она проверяет JWT (подпись по JWKS или локальному ключу) и из этого токена достает права доступа для этого запроса.
«Провижнинг» пользователя в базу (JIT) выполняется при первом успешном запросе с валидным токеном IdP только если в токене есть маппируемая роль (см. OIDC_ROLE_CLAIM / OIDC_ROLE_MAP). Запасной роли «по умолчанию» нет; без маппируемой роли учётку не создают, запрос отклоняют (403). Если вы оставляете локальный вход включённым, встроенные учётные записи и выдача JWT через POST /login продолжают работать параллельно с IdP (гибридный режим).
Вся коммуникация с IdP происходит по протоколу HTTP(S). Поддержка протоколов LDAP и т.п. происходит через внешнюю систему (через сам IdP).
OIDC не является единственно возможным режимом, по умолчанию Agora работает с встроенной базой пользователей и позволяет самостоятельно управлять пользователями. При этом по сути Agora будет самостоятельно себе выписывать JWT токены.
Настройка OIDC может быть достаточно комплексной, требует настроить много разных деталей и учитывая вариативность корпоративных инсталяций, может быть достаточно громоздкой.
Дальше в документе описываются шаги, позволяющие повторить у себя в окружении базовые вещи и потом настроить сценарий посложнее:
- Как запустить OIDC вместе с локально запущенным Authentik
- Какие поля в JWT используются у нас
- Какие опции настройки OIDC есть в Agora
- Глоссарий с терминами, используемыми в этом описании
1. Как запустить OIDC вместе с Authentik¶
1.1. Развёртывание Authentik¶
Полная установка Authentik (Docker Compose, Kubernetes, интеграция с LDAP и т.д.) описана в официальной документации Authentik.
В этом мануале мы запустим Agora и Authentik на сервере в локальной сети с помощью Docker Compose для того, чтобы получить общее представление о конфигурации OIDC. При переносе этой конфигурации в продакшн, подход к настройке не изменится.
Для начала запустим Authentik в локальной конфигурации:
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .authentik-env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .authentik-env
curl -o authentik-compose.yml https://docs.goauthentik.io/compose.yml
docker compose -f authentik-compose.yml --env-file .authentik-env -p authentik up -d
Если что-то пойдет не так, всегда можно остановить полностью удалить authentik:
docker compose -f authentik-compose.yml --env-file .authentik-env -p authentik down -v
Теперь пройдем по адресу http://authentik.local:9000/if/flow/initial-setup/ Здесь authentik.local - адрес сервера, на котором вы запустили этот IdP. В простом варианте это может быть localhost, но главное чтобы на него мог перейти браузер. В этом интерфейсе надо создать администратора для Authentik. Совершенно неважно, что тут указать, это временная инсталяция.
1.2. Настраиваем Authentik¶
- Создайте в Authentik Application (приложение) с именем Agora (slug впишется автоматически).


- Создайте OAuth2/OIDC Provider (просто выберите его в списке)

- Выберите Authorization flow implicit (default-provider-authorization-implicit-consent)

- На этой странице надо поменять Client ID на
agora-admin-api. Так будет проще потом. Скопируйте с этой страницы Client Secret. Их надо будет поместить в опцииOIDC_CLIENT_IDиOIDC_CLIENT_SECRET(см ниже раздел настроек Agora)
Здесь же надо зайти в расширенные настройки Advanced protocol settings и добавить offline_access к доступным Scopes.

- На следующей странице пропускаем добавление групп, потому что их ещё нет
- На последней странице выбираем Submit и приложение создано

- Далее надо зайти в раздел групп

- Создать две новых группы, например "Content managers" и "Security"

- Получится список из нескольких групп

- Теперь идем в раздел пользователей создавать нового для теста

- Создаем нового, назовем его "Event Manager 1" (возможно, друзья зовут его как-то по-другому, но нам это сейчас не принципиально)

- Пользователь создан
- И можно перейти на его карточку

- Идем во вкладку "Groups"

- Добавляем группу

- Выбираем имеющуюся группу "Content managers"

- Сохраняем и возвращаемся во вкладку групп пользователя

- Последний шаг: добавляем пароль пользователю

1.2. Настройка Agora¶
Для того, чтобы Agora могла работать по OIDC с IdP надо настроить следующие переменные окружения:
OIDC_AUDIENCE=agora-admin-api- этот параметр мы ожидаем в aud клейме внутри JWT, пришедшего от IdPOIDC_CLIENT_ID=agora-admin-api- здесь мы списываем по сути логин от записи о нашем приложении в IdPOIDC_CLIENT_SECRET=oCSarud3XmFrYyjVl....ko1VW8n2O3SJLHfwCoTiyэто пароль от записи о нашем приложенииOIDC_SCOPES="openid profile offline_access"эта настройка опциональная, здесь выписаны те дефолты, которые уже есть в Agora. offline_access нужен для того, чтобы можно было обновлять авторизационный токенOIDC_ISSUER=http://authentik.local:9000/application/o/agora/- надо вписать адрес вашего сервера, например того authentik, который мы настроили в примере выше. Важно, что в этом путиagora- это соглашение самого authentik, на то, что Slug приложения будет участвовать в пути к Issuer ресурсуOIDC_TITLE=Authentik- сюда нужно вписать что захотите, это то сообщение, которое будет выводиться пользователям. Без этой опции OIDC не включается.OIDC_ROLE_CLAIM=groups- опциональная настройка, указывает в каком поле внутри JWT прийдет список групп пользователяOIDC_ROLE_MAP='{"authentik Admins":"administrator","Content managers":"content_manager","Sysops":"monitoring"}'- важное и сложное поле, без него ничего не заработает. В нём указывается, как превращаются группы из IdP в роли внутри Agora (см дальше список ролей)LOCAL_LOGIN_ENABLED=false- можно опционально выключить авторизацию по логину-паролю и оставить только через IdP
1.3. Шаги пользователя системы¶
- Пользователь заходит на экран логина и видит два варианта авторизации: локальный и через OIDC

- Выбирает вход через IdP и попадает в приложение Authentik

- Вводит свой логин (конкретно в этом примере "Event Manager 1") и переходит на экран ввода пароля

- После успешного ввода пароля пользователь возвращается на экран Agora и автоматически логинится в приложение

Пользователь успешно создан в системе Agora.
2. Детали настройки¶
2.1. Роли в IdP и сопоставление с Agora¶
Ниже практический алгоритм для администратора, как настроить сопоставление ролей IdP -> Agora.
Agora берет значение роли из access token:
- имя claim (поля в JWT токене) задает переменная окружения
OIDC_ROLE_CLAIM; - сопоставление строк из токена с ролями Agora задает
OIDC_ROLE_MAP.
Допустимые роли в Agora:
administrator;content_manager;monitoring;security.
Если для нового пользователя не найдено ни одного совпадения в OIDC_ROLE_MAP, вход завершается 403, учетная запись по JIT схеме не создается.
Если учетная запись уже существует и в новом токене нет маппируемой роли, текущая Account.role не меняется.
Пошаговая настройка¶
- Определите, из какого claim будете брать роль.
Чаще всего это groups (массив строк), реже отдельный строковый claim.
- Настройте IdP, чтобы нужный claim попадал в access token.
Для Authentik обычно делают Scope/Property Mapping и подключают его к нужному OAuth2/OpenID Provider, но из коробки всё настроено на groups и ничего делать не надо.
- Убедитесь, что значения в claim стабильны и удобны для маппинга.
Пример значений групп: agora-administrator, agora-content-manager, agora-monitoring, agora-security. Так же можно использовать более человеко-читаемые, как в примере выше: Content managers
- Настройте переменные Agora.
OIDC_ROLE_CLAIM=groups
OIDC_ROLE_MAP='{"agora-administrator":"administrator","agora-content-manager":"content_manager","agora-monitoring":"monitoring","agora-security":"security"}'
- Перезапустите Agora, выполните новый login через IdP и проверьте результат.
Проверка и отладка¶
В логах Agora вы увидите декодированный токен:
{"level":"info","token_endpoint":"http://localhost:9000/application/o/token/","has_refresh_token":true,"expires_in":300,"access_token_payload":"{\"iss\":\"http://localhost:9000/application/o/agora/\",\"sub\":\"4b34f838bad570b486a2168b5353666fc19a77a230f9df03aff8c1bf7c1baf77\",\"aud\":\"agora-admin-api\",\"exp\":1775037446,\"iat\":1775037146,\"auth_time\":1775037103,\"acr\":\"goauthentik.io/providers/oauth2/default\",\"amr\":[\"pwd\"],\"sid\":\"1799899e3648369f24a47c987310fd96a5c5678dce14bbdcf61ce67c4e61b430\",\"jti\":\"oUgCDmUr9jtxiBn2zN4N0ExsZV4rptZ8eUuajmOy\",\"name\":\"\",\"given_name\":\"\",\"preferred_username\":\"Event Manager 1\",\"nickname\":\"Event Manager 1\",\"groups\":[\"Content managers\"],\"azp\":\"agora-admin-api\",\"uid\":\"yfgs9bVO0Lg2Okc3c0HdDjN5OxxGG1SlHen4b1l4\",\"scope\":\"openid profile offline_access\"}","time":1775037146,"message":"oidc: token response received"}
{"level":"info","jwks_url":"http://localhost:9000/application/o/agora/jwks/","keys":1,"ttl":3600000,"time":1775037146,"message":"oidc: jwks cache refreshed"}
{"level":"info","issuer":"http://localhost:9000/application/o/agora/","subject":"4b34f838bad570b486a2168b5353666fc19a77a230f9df03aff8c1bf7c1baf77","jti":"oUgCDmUr9jtxiBn2zN4N0ExsZV4rptZ8eUuajmOy","exp":1775037446,"time":1775037146,"message":"oidc: access token verified"}
Можно проверить, что именно приходит в поле groups
Проверьте логи backend:
-
при проблеме маппинга будет
oidc login: no mappable role for JIT user; -
при успешном маппинге увидите успешный
POST /login/oidcи создание/вход в учетку.
Для shell-конфигураций используйте OIDC_ROLE_MAP как одну JSON-строку в кавычках (как в примере выше), чтобы избежать искажения формата при source .env.
1.6. Сессии в Agora и отзыв¶
Agora работает по паттерну BFF (Backend for Frontend): браузер не хранит и не отправляет JWT IdP в API. Браузер использует обычный session token Agora (opaque), а backend сам работает с access/refresh token IdP.
Подход соответствует рекомендациям IETF для browser-based приложений: OAuth 2.0 for Browser-Based Applications (BFF).
Идентификатор сессии Agora (session_id) для OIDC-логина инициализируется из первого jti access token IdP и дальше остается стабильным для этой локальной сессии.
-
GET /sessions,GET /sessions/{id}—{id}этоjti. -
session_logout— завершение поjti.
Для OIDC-сессии logout закрывает локальную сессию Agora. Если у IdP объявлен revocation_endpoint, backend дополнительно отправляет revoke для refresh token (best effort).
После закрытия сессии Agora отвечает 401 по этому session token.
1.7. Проверка после связки с IdP¶
-
OIDC_ISSUER,OIDC_AUDIENCE, JWKS совпадают с реальным access token. -
Логин через OIDC в UI и успешный вход в админку.
-
JIT: новый
subи маппируемая роль в токене → учётка в MongoDB, верная роль; без маппируемой роли → 403, учётки нет. -
Отзыв сессии по
jti.
2. Какие поля в access token IdP использует backend Agora¶
Ниже — поля access token IdP, которые backend Agora проверяет и использует в OIDC-flow. Браузер в API Agora JWT не отправляет.
| Claim / аспект | Назначение для Agora |
|---|---|
iss |
Должен совпадать с OIDC_ISSUER. |
aud |
Должен содержать agora-admin-api (строка или элемент массива). |
sub |
Стабильный идентификатор пользователя у IdP; связывается с external_account_id в MongoDB. |
jti |
Обязателен; идентификатор сессии в API и в аудите (session_id). Без jti — 401. |
exp |
Срок действия токена; проверка с leeway 120 с (допуск по часам). |
nbf |
Не обязателен; если есть — «не раньше» с тем же leeway 120 с. |
iat |
Стандартное время выдачи; может использоваться вспомогательно. |
Claim из OIDC_ROLE_CLAIM |
Строка или массив строк (например группы); маппинг в роль Agora через OIDC_ROLE_MAP. |
preferred_username, email |
Участвуют в выборе логина при JIT (вместе с sub). |
Дополнительно Agora использует заголовок JWT kid при выборе ключа из JWKS и кэшировании ключей (OIDC_JWKS_CACHE_TTL, повторная загрузка JWKS при сбое проверки подписи — по логике вашей сборки).
4. Глоссарий¶
- OIDC — OpenID Connect. Протокол входа и выдачи JWT без постоянных запросов приложения к каталогу при каждом действии пользователя.
- JWT — JSON Web Token. Подписанное сообщение с полями (claims): кто пользователь, до когда токен действителен, для кого он выдан. Содержимое видно, подделать без ключа нельзя.
- IdP — Identity Provider. Центральный корпоративный каталог, хранящий пользователей и политики доступа; выдаёт токены клиенту после входа.
- Claim — одно именованное поле внутри JWT (
sub,aud,groupsи т.д.). - Access token — JWT IdP, который backend Agora использует для валидации личности и ролей. Браузер этот токен в API Agora не отправляет.
- ID token — JWT «о факте входа» в браузере. Для админского API Agora не используется (другой
audи назначение). - JWKS — JSON Web Key Set. Публичные ключи IdP (отдельным URL); по ним Agora проверяет подпись access token. Например этот список запрашивается у IdP.
- RS256 — подпись JWT алгоритмом RSA-SHA256. Типично у access token, который выдает IdP.
- OAuth2 / OpenID Provider — часть IdP, которая по протоколу OAuth2/OIDC отдаёт клиенту access (и при необходимости ID) токены.
- Discovery — стандартный JSON по адресу
{issuer}/.well-known/openid-configuration: оттуда берутissuer,jwks_uriи прочие конечные точки. - Scope — набор прав/данных, который клиент запрашивает при авторизации; от настроек scope зависит, какие claims попадут в токен.
- Audience (
aud) — в JWT указано, для какого приложения выдан токен. Для Agora в access token должно бытьagora-admin-api(или это значение в спискеaud). - Bearer — схема в HTTP:
Authorization: Bearer <токен>. В нашей схеме браузер передает Bearer session token Agora, а не JWT IdP. - JIT (Just-In-Time) — первый успешный запрос к Agora с валидным токеном IdP создаёт учётную запись в базе, если её ещё не было и в токене есть маппируемая роль; иначе учётку не создают (403).
- Property Mapping (в Authentik) — правило «какие поля добавить в access token» (например список групп); без маппинга группы могут не попасть в JWT.
iss(issuer) — кто выдал JWT (URL IdP). Agora поissвыбирает нужный JWKS для проверки подписи.sub(subject) — неизменяемый идентификатор пользователя у IdP; в Agora хранится как связь с внешним аккаунтом (external_account_id).jti(JWT ID) — уникальный номер выпуска access token IdP. Для OIDC-сессии Agora используетjtiпервого успешного токена как стабильныйsession_id.exp/nbf— до какого момента токен действителен и (если есть) с какого момента его уже можно принимать.- SSO — single sign-on: пользователь один раз аутентифицируется в IdP, приложения используют выданные токены.
- End session — URL у IdP для завершения сессии в браузере («выйти везде»), в отличие от простого сброса токена на стороне клиента.