Skip to content

Использование 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 может быть достаточно комплексной, требует настроить много разных деталей и учитывая вариативность корпоративных инсталяций, может быть достаточно громоздкой.

Дальше в документе описываются шаги, позволяющие повторить у себя в окружении базовые вещи и потом настроить сценарий посложнее:

  1. Как запустить OIDC вместе с локально запущенным Authentik
  2. Какие поля в JWT используются у нас
  3. Какие опции настройки OIDC есть в Agora
  4. Глоссарий с терминами, используемыми в этом описании

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

  1. Создайте в Authentik Application (приложение) с именем Agora (slug впишется автоматически).

authentik-1-new-app

authentik-2-agora

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

authentik-3-provider

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

authentik-4-flow

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

Здесь же надо зайти в расширенные настройки Advanced protocol settings и добавить offline_access к доступным Scopes.

authentik-4-provider-scopes

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

authentik-5-apps

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

authentik-10-no-groups

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

authentik-11-new-group

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

authentik-12-groups

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

authentik-20-no-users

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

authentik-21-new-user

  1. Пользователь создан

authentik-22-user-created

  1. И можно перейти на его карточку

authentik-23-user-card

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

authentik-24-user-groups

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

authentik-24-new-group

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

authentik-26-group-selected

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

authentik-27-group-added

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

authentik-28-password

1.2. Настройка Agora

Для того, чтобы Agora могла работать по OIDC с IdP надо настроить следующие переменные окружения:

  • OIDC_AUDIENCE=agora-admin-api - этот параметр мы ожидаем в aud клейме внутри JWT, пришедшего от IdP
  • OIDC_CLIENT_ID=agora-admin-api - здесь мы списываем по сути логин от записи о нашем приложении в IdP
  • OIDC_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. Шаги пользователя системы

  1. Пользователь заходит на экран логина и видит два варианта авторизации: локальный и через OIDC

agora-1-login

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

agora-2-authentik

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

agora-3-password

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

agora-4-success

Пользователь успешно создан в системе 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 не меняется.

Пошаговая настройка

  1. Определите, из какого claim будете брать роль.

Чаще всего это groups (массив строк), реже отдельный строковый claim.

  1. Настройте IdP, чтобы нужный claim попадал в access token.

Для Authentik обычно делают Scope/Property Mapping и подключают его к нужному OAuth2/OpenID Provider, но из коробки всё настроено на groups и ничего делать не надо.

  1. Убедитесь, что значения в claim стабильны и удобны для маппинга.

Пример значений групп: agora-administrator, agora-content-manager, agora-monitoring, agora-security. Так же можно использовать более человеко-читаемые, как в примере выше: Content managers

  1. Настройте переменные Agora.
OIDC_ROLE_CLAIM=groups
OIDC_ROLE_MAP='{"agora-administrator":"administrator","agora-content-manager":"content_manager","agora-monitoring":"monitoring","agora-security":"security"}'
  1. Перезапустите 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

  1. OIDC_ISSUER, OIDC_AUDIENCE, JWKS совпадают с реальным access token.

  2. Логин через OIDC в UI и успешный вход в админку.

  3. JIT: новый sub и маппируемая роль в токене → учётка в MongoDB, верная роль; без маппируемой роли → 403, учётки нет.

  4. Отзыв сессии по 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). Без jti401.
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 для завершения сессии в браузере («выйти везде»), в отличие от простого сброса токена на стороне клиента.