OIDC снаружи выглядит просто — при интеграции на каждое приложение он полон ловушек
OpenID Connect, построенный поверх OAuth 2.0, является доминирующим протоколом федеративной идентичности для современных стеков. Каждый крупный корпоративный IdP его поддерживает; каждый облачный workforce IdP его предлагает; каждый современный фреймворк приложений предоставляет для него библиотеку. Кажущейся лёгкой частью является предположение, что нескольких строк SDK-кода на приложение будет достаточно.
На практике у OIDC relying party, несущего реальный продакшн-трафик, есть длинный список того, что нужно сделать правильно. Подпись ID token должна проверяться по JWKS, опубликованному IdP, с выбором правильного ключа по kid, а кэш должен обновляться, когда IdP проводит ротацию ключей. Claim audience обязан совпадать с настроенным client ID. Issuer должен совпадать с настроенным ожидаемым issuer. Срок действия должен проверяться с ограниченным допуском на расхождение часов. Nonce внутри ID token обязан совпадать с nonce, который AAM отправил в запросе авторизации, — если не совпадает, это не ошибка разбора, а попытка повторного воспроизведения.
У нижележащего слоя OAuth 2.0 свои ловушки. State должен привязываться к сессии пользователя как защита от CSRF и иметь короткий TTL. PKCE должен использоваться (предпочтительно S256), чтобы перехваченный authorization code не мог быть обменян злоумышленником. Mixup-атаки — когда злоумышленник обманом заставляет relying party общаться с неправильным IdP — отражаются привязкой callback к конкретному IdP и проверкой issuer соответственно. В наивной SDK-интеграции ни одна из этих защит не работает автоматически.
Другая форма провала — встраивать OIDC SDK напрямую в каждое приложение. В этом случае каждое приложение по отдельности несёт свои решения о доверии, кэш JWKS, журналы аудита и конфигурацию IdP. Одно изменение IdP превращается в скоординированный многоприложенческий релиз. MFA, условный доступ, доверие устройства и поведение при выходе решаются отдельно для каждого приложения, зачастую несогласованно.
Операционная сторона столь же важна. Обновление discovery-документа IdP, обработка ротации ключей подписи, маршрутизация к разным IdP по тенанту, разные сопоставления claim'ов для разных приложений и потоки выхода — это не мелкие детали, добавляемые позже. Это базовые части того, что заставляет OIDC-федерацию работать безопасно и устойчиво.
Правильное место — край доступа. OIDC должен проверяться в одной точке; управляться на том же слое, что и аутентификация, MFA, условный доступ, доверие устройства и Backend SSO. Тогда приложения не несут сложность протокола федерации; они получают только проверенную, чистую и доверенную идентичность.
Правильно управлять OIDC — это не просто подключиться к IdP через SDK. Это проверять ID token в одной точке — в том же движке, что и MFA, условный доступ, доверие устройства и Backend SSO — соответствующим стандартам образом, проводить аудит и безопасно доставлять идентичность приложениям.
Наш подход
Один шлюз AAM правильно завершает OIDC на краю; остальная часть движка доступа надстраивается над этим.
Полноценный OpenID Connect relying party плюс OAuth 2.0 клиент
Authorization code flow с PKCE, проверка подписи ID token через JWKS, защита от повторного воспроизведения на основе nonce, защита от CSRF на основе state, применение audience/issuer/срока действия. Тот же движок говорит на чистом OAuth 2.0 для IdP, не выдающих ID token; так провайдеры, предоставляющие только токены, и полноценные OIDC-провайдеры разделяют одну кодовую базу.
Маршрутизация IdP по приложению и тенанту
Один шлюз AAM может одновременно маршрутизировать разные приложения к разным IdP и разные тенанты одного приложения к разным IdP. Выбор IdP делается для каждого запроса из контекста приложения или тенанта — никакого отдельного шлюза на каждый IdP, никакого ручного селектора для пользователя.
Атаки повторного воспроизведения, CSRF и mixup отражаются по умолчанию
Nonce привязывает ID token к запросившему его запросу авторизации; state привязывает callback к сессии пользователя; PKCE привязывает обмен кода к исходному публичному клиенту. Ни один из этих механизмов не является опциональным флагом, который интегратор может забыть, — это сам поток по умолчанию.
Согласовано с MFA, условным доступом, доверием устройства и Backend SSO
OIDC-аутентификация не работает сама по себе — она компонуется с edge MFA (если IdP не применил step-up), выражениями условного доступа, непрерывной оценкой доверия и инъекцией Backend SSO в backend. ID token становится входом в сессию AAM; не всей сессией.
Возможности
OIDC relying party, соответствующий стандартам, плюс операционные функции, делающие федерацию безопасной и управляемой в масштабе.
Authorization code flow с PKCE (по умолчанию S256)
AAM инициирует OAuth 2.0 authorization code flow с включённым по умолчанию PKCE — code_challenge_method=S256, свежий code_verifier на каждый запрос, никогда не переиспользуется. Злоумышленник, не сгенерировавший verifier, не может обменять перехваченный authorization code на токены. Чистый PKCE остаётся доступным для IdP, которые этого требуют; S256 — настроенное значение по умолчанию.
Проверка подписи ID token по JWKS IdP
При поступлении callback AAM получает JWKS IdP, выбирает ключ подписи по заголовку kid ID token и проверяет подпись ID token указанным в заголовке алгоритмом (RS256 и остальное стандартное семейство). Промах кэша по kid немедленно обновляет JWKS; так ротация ключей IdP не блокирует действительные входы.
Audience, issuer, действительность и nonce — не только разбираются, но применяются
Claim audience ID token обязан содержать настроенный client ID; issuer должен совпадать с настроенным ожидаемым issuer; окно действия (exp/nbf) применяется с ограниченным допуском на расхождение часов; nonce обязан совпадать с nonce, отправленным AAM в запросе авторизации. Несовпадение nonce обрабатывается не как ошибка разбора, а как сигнал повторного воспроизведения со своим собственным событием аудита.
Общий кэш JWKS с обновлением-при-промахе для ротации ключей
Ответы JWKS кэшируются в хранилище, общем для рабочих процессов и экземпляров шлюза, с TTL в 1 час. Попадание в кэш устраняет сетевой round-trip при каждом входе; промах кэша по запрошенному kid мгновенно запускает обновление с JWKS URI; так рутинная ротация ключей IdP не вызывает прерывания входа.
Параметры OIDC: scope, display, max_age, ui_locales, acr_values
Стандартные параметры авторизации OIDC являются первоклассной конфигурацией: scope (openid добавляется автоматически), display для опыта входа в IdP, max_age для обязательной повторной аутентификации, ui_locales для локализованных страниц IdP и acr_values для запроса конкретного класса контекста аутентификации — полезно для запроса step-up MFA у IdP.
Встроенные профили провайдеров плюс полностью пользовательские IdP
Встроенные профили поставляются с разумными значениями по умолчанию для распространённых провайдеров (well-known эндпоинты, JWKS URI, привычки по scope). Путь пользовательского IdP, где эндпоинты, scope'ы и сопоставления задаются вручную, остаётся доступным для любого OIDC- или OAuth 2.0-провайдера, соответствующего стандартам.
Claim'ы ID token объединяются с userinfo; подписанные claim'ы приоритетны
После проверки подписи claim'ы ID token объединяются с ответом эндпоинта userinfo IdP. При конфликте подписанные claim'ы ID token считаются приоритетными над неподписанными полями userinfo; так злоумышленник, подделывающий ответ userinfo, не может тихо изменить подписанный claim идентичности.
Операционная глубина
Механика, которая держит OIDC-федерацию безопасной, актуальной и наблюдаемой.
Привязка state с TTL в 10 минут и контролем сессии
Параметр OAuth state хранится привязанным к сессии пользователя с TTL в 10 минут. При поступлении callback AAM проверяет, что state принадлежит той же сессии, что инициировала поток — злоумышленник, повторно воспроизводящий значение state в браузере другого пользователя, отклоняется с событием аудита OAUTH_STATE_MISMATCH.
Аудит каждого пропуска проверки ID token — по корневой причине
Когда проверка подписи ID token пропускается по операционной причине — JWKS недоступен, нет совпадающего kid, повреждённый JWK, отсутствует JWKS URI — специальное событие аудита фиксирует конкретную корневую причину. Операторы могут отличить временный сбой JWKS от неверной конфигурации или неподдерживаемого типа ключа без перечитывания runtime-логов.
Ограниченный допуск на расхождение часов на каждый IdP
ID token несут временные метки iat, nbf и exp. Реальные часы дрейфуют; AAM применяет ограниченный допуск на расхождение часов (по умолчанию 60 секунд для нижележащего JWT-валидатора); так небольшой дрейф не отклоняет действительные входы, а большой дрейф — индикатор неверной конфигурации или повторного воспроизведения — всё равно отклоняется.
Обмен токенами и userinfo с усиленными сетевыми тайм-аутами
Запросы обмена токенами и userinfo к IdP используют ограниченные тайм-ауты соединения, DNS и общий; так медленный или не отвечающий IdP не может занять рабочие процессы шлюза. Обмен токенами работает с общим бюджетом в 30 секунд; userinfo работает с бюджетом в 15 секунд; у обоих бюджеты соединения и DNS короче; так сбои происходят быстро.
Аудит на каждое событие с корреляцией к сессии AAM
Каждый шаг OIDC-потока — начало потока, успех callback, обмен токенами (какие токены вернулись), результат проверки подписи ID token, результат получения JWKS — записывается с correlation ID, привязанным к сессии AAM и стоящим за ней backend(ам). Вопрос «кто, через какой IdP и когда вошёл в систему» отвечается одним запросом.
Какие команды используют
Современные корпоративные IdP (Entra ID, Okta, Auth0, Keycloak)
Существующие корпоративные IdP, уже аутентифицирующие рабочую силу через OIDC. AAM подключается как relying party, не требуя от команды IdP что-либо менять. Новые приложения присоединяются к федерации, добавляя запись в AAM, а не новый OIDC SDK в каждую кодовую базу.
Workforce social IdP (Google Workspace, GitHub)
Внутренние инструменты, аутентифицирующие против Google Workspace тенанта организации, или инструменты разработчиков, использующие GitHub как IdP. AAM говорит на OIDC с Google и на OAuth 2.0 с GitHub — из одного движка — и сопоставляет каждого с каноническим форматом сессии AAM.
Мультитенантный SaaS с OIDC IdP на каждый тенант
SaaS-приложения, где каждый клиент приносит свой собственный OIDC IdP. Один шлюз AAM держит все тенанты впереди; трафик каждого тенанта маршрутизируется к IdP этого тенанта. Добавить тенант — это не развёртывание, а изменение конфигурации в реестре IdP.
Edge MFA и условный доступ поверх OIDC IdP
Некоторые IdP аутентифицируют, но не применяют step-up MFA или условный доступ равномерно для каждого приложения. AAM принимает аутентификацию IdP, затем надстраивает над ней собственную MFA, выражения условного доступа и непрерывную оценку доверия перед предоставлением доступа к приложению.
Часто задаваемые вопросы
С какими IdP AAM федерируется через OIDC и OAuth 2.0?
Как AAM защищается от повторного воспроизведения ID token, CSRF и mixup-атак?
Что происходит, когда IdP проводит ротацию ключей подписи?
В чём разница между OIDC и чистым OAuth 2.0 на этой странице?
Что происходит с идентичностью после того, как AAM получает токены?
OIDC, сделанный правильно, на краю
Подключим AAM к вашему OIDC IdP — корпоративному, облачному или self-hosted — и надстроим остальную часть движка доступа над проверенным ID token с MFA, условным доступом, доверием устройства и Backend SSO.