Как настроить безопасную OIDC-аутентификацию в Yandex Identity Hub

Разбираем, как выбрать тип OIDC-приложения, настроить Redirect URI, scopes и PKCE, провести Authorization Code Flow и проверить ID-токен в Yandex Identity Hub.

Краткий пересказ YandexGPT
  • OpenID Connect (OIDC) работает поверх OAuth 2.0 и позволяет приложению узнать, кто прошёл аутентификацию, используя ID-токен и ресурс UserInfo. OAuth 2.0 отвечает за делегирование доступа, а OIDC добавляет слой идентификации пользователя. Это позволяет реализовать единый вход (Single Sign-On, SSO).
  • В сценарии OIDC участвуют четыре роли: Resource Owner (пользователь), Client (приложение), Authorization Server (сторона, которая аутентифицирует пользователя и выпускает токены) и Resource Server (защищённый ресурс).
  • В Yandex Identity Hub доступны три типа OIDC-приложений: Web Application, Single-Page Application и Native Application.
  • OAuth-клиенты делятся на два типа: Confidential client (может безопасно хранить учётные данные приложения) и Public client (не может безопасно хранить секрет и выполнять полноценную аутентификацию клиента).
  • PKCE (Proof Key for Code Exchange) используется для подтверждения, что Authorization Code Flow завершает та же сторона, которая его начала. Для публичных клиентов PKCE обязателен, для Web Application в Yandex Identity Hub его можно отключить.
  • Для настройки OIDC-приложения в Yandex Identity Hub нужно выбрать тип приложения, указать Redirect URI, настроить аутентификацию клиента, определить обязательность PKCE, ограничить scopes, добавить пользователей и группы, создать секрет для Web Application.
  • ID-токен содержит информацию о пользователе, который прошёл аутентификацию, и выпускается в формате JWT. Access-токен используется для обращения к ресурсу UserInfo.
  • Безопасность OIDC-интеграции зависит от нескольких факторов: типа приложения, использования PKCE, ограничения scopes, проверки Redirect URI, state и nonce, проверки подписи ID-токена.

OpenID Connect позволяет приложению передать аутентификацию пользователя доверенной стороне и получить подтверждённую информацию о его личности. При этом безопасность интеграции зависит не только от поддержки протокола, но и от конкретных настроек: типа клиента, Redirect URI, состава scopes, использования PKCE и проверки токенов.

Ниже разберём эти элементы на примере настройки OIDC-приложения в Yandex Identity Hub.

Эту статью мы подготовили на основе вебинара «Как безопасно настраивать OIDC-приложения с Yandex Identity Hub».

Подробнее о возможностях сервиса можно узнать на странице Yandex Identity Hub, в документации или нашей статье «Yandex Identity Hub: централизованное управление пользователями и доступом к приложениям».

Как связаны OAuth 2.0 и OpenID Connect

OAuth 2.0 — это фреймворк делегированного доступа. Он позволяет приложению получить ограниченные полномочия от имени пользователя или от собственного имени, не запрашивая у пользователя его учётные данные.

Простой пример — сторонний сервис, которому пользователь разрешает читать фотографии из социальной сети. Пользователь не передаёт сервису логин и пароль, а предоставляет ограниченный доступ: например, только к фотографиям и только на чтение.

OpenID Connect, или OIDC, работает поверх OAuth 2.0 и решает другую задачу: позволяет приложению узнать, кто именно прошёл аутентификацию. Для этого протокол предусматривает два основных источника информации:

Таким образом, OAuth 2.0 отвечает за делегирование доступа, а OpenID Connect добавляет слой идентификации пользователя. На этой основе можно реализовать единый вход, или Single Sign-On (SSO).

OAuth 2.0 предоставляет приложению ограниченный доступ к защищённому ресурсу. OpenID Connect дополняет этот механизм идентификацией пользователя с помощью ID-токена и UserInfo

Основные роли в OIDC

В сценарии OpenID Connect участвуют четыре роли:

  • Resource Owner — владелец ресурса, обычно пользователь.
  • Client, или Relying Party, — приложение, которое хочет аутентифицировать пользователя и получить информацию о нём.
  • Authorization Server, или OpenID Provider, — сторона, которая аутентифицирует пользователя и выпускает токены.
  • Resource Server — защищённый ресурс, к которому клиент обращается с access-токеном.

В рассматриваемой схеме Yandex Identity Hub выполняет роль OpenID Provider и Authorization Server.

Почему рассматриваем Authorization Code Flow

Authorization grant — это разрешение, которое пользователь предоставляет приложению и которое клиент затем использует для получения токенов. Существуют разные типы грантов (grant types) и связанные с ними последовательности действий (flows).

В вебинаре мы рассматривали Authorization Code Flow — распространённый сценарий OpenID Connect, который подходит для разбираемой задачи.

Как выбрать тип OIDC-приложения

В Yandex Identity Hub доступны три типа OIDC-приложений: Web Application, Single-Page Application и Native Application.

OAuth-клиенты делятся на два базовых типа:

  • Confidential client — может безопасно хранить учётные данные приложения или надёжно аутентифицироваться другим способом.
  • Public client — не может безопасно хранить секрет и выполнять полноценную аутентификацию клиента.

На практике тип клиента связан с профилем приложения.

Типы OIDC-клиентов и требования к их настройке

Профиль клиента определяет доступные методы аутентификации, допустимые Redirect URI и требования к PKCE.

Тип клиента

Профиль клиента

Методы аутентификации

Разрешённые Redirect URI

Обязательность PKCE

Confidential

Web

client_secret_basic; client_secret_post

HTTPS; HTTP только для loopback-адресов

Можно включить или отключить

Public

User-agent based

Не используются

HTTPS; HTTP только для loopback-адресов

Обязателен

Public

Native

Не используются

HTTPS; HTTP только для loopback-адресов; произвольные URI-схемы, например vscode://demo/callback

Обязателен

В терминологии Yandex Identity Hub профилю Web соответствует тип приложения Web Application, профилю User-agent based — Single-Page Application, а профилю Native — Native Application. После создания приложения изменить его тип нельзя, поэтому выбрать профиль нужно до настройки остальных параметров.

Для Web Application обязательность PKCE можно включить или отключить. Для публичных клиентов PKCE обязателен.

Почему для большинства веб-приложений подходит Web Application

Если у приложения есть серверная часть, базовый выбор для большинства сценариев — Web Application. В этом случае authorization code можно обменять на токены на бэкенде и там же аутентифицировать клиент с помощью client_id и client_secret.

Такой подход безопаснее и понятнее, чем получать токены на клиентской стороне, а затем передавать их на сервер с недоверенной стороны.

Профиль Single-Page Application нужен для приложения, которое работает в браузере и не имеет доверенной серверной части для хранения секрета. Такой клиент считается публичным: у него нет client_secret, а PKCE нельзя отключить.

Для нативных приложений могут использоваться произвольные URI-схемы, чтобы перенаправлять пользователя непосредственно в мобильное или десктопное приложение.

Зачем нужен PKCE

PKCE расшифровывается как Proof Key for Code Exchange. Механизм описан в RFC 7636. Его задача — подтвердить, что Authorization Code Flow завершает та же сторона, которая его начала.

Механизм работает так:

  1. Приложение генерирует случайную строку code_verifier.
  2. На её основе вычисляет code_challenge, например методом S256.
  3. В authorization request приложение передаёт code_challenge и метод его вычисления.
  4. При обращении к token endpoint приложение передаёт исходный code_verifier.
  5. Authorization Server сопоставляет два запроса и проверяет их связь.

Для публичных клиентов PKCE включён по умолчанию и не отключается. Для Web Application в Yandex Identity Hub требование PKCE также включено по умолчанию, но его можно отключить.

Даже если обязательность PKCE отключена, нельзя начать flow с параметрами PKCE, а завершить его без code_verifier: такой даунгрейд не сработает. Если PKCE использовался в authorization request, он должен использоваться и в token request.

Как настроить OIDC-приложение в Yandex Identity Hub

Полную последовательность действий мы раскрывали в инструкции «Как создать OIDC-приложение в Yandex Identity Hub».

Когда определитесь с типом клиента, создайте OIDC-приложение в Yandex Identity Hub, а затем настройте его по шагам ниже.

Шаг первый. Выберите тип приложения

При создании приложения выберите OpenID Connect, а затем подходящий тип: Web Application, Single-Page Application или Native Application.

Выбор определит:

  • можно ли создать секрет приложения
  • какие методы аутентификации клиента доступны
  • какие Redirect URI разрешены
  • можно ли отключить обязательное использование PKCE

Шаг второй. Укажите Redirect URI

Redirect URI — адрес, на который Authorization Server перенаправляет пользователя после завершения авторизации и передаёт authorization code.

Для рабочего приложения типов Web Application и Single-Page Application нужно указывать HTTPS-адрес callback endpoint. HTTP разрешён только для тестирования на локальном хосте — http://127.0.0.1 или http://localhost. Для Native Application могут использоваться другие корректные схемы URI.

Redirect URI в запросе должен полностью совпадать с адресом, зарегистрированным в Yandex Identity Hub. Даже отличие в один символ приведёт к ошибке.

Подробнее о требованиях к Redirect URI можно прочитать в разделе об OIDC-приложениях Yandex Identity Hub.

Шаг третий. Настройте аутентификацию клиента

Для Web Application доступны два метода:

  • client_secret_basic — client_id и client_secret передаются в заголовке Authorization.
  • client_secret_post — client_id и client_secret передаются в теле запроса.

Для публичных клиентов методы аутентификации недоступны: приложение не получает и не передаёт секрет.

Шаг четвёртый. Определите обязательность PKCE

Для Web Application можно включить или отключить требование PKCE. Для Single-Page Application и Native Application PKCE включён обязательно.

Шаг пятый. Ограничьте scopes

Scopes определяют, какую информацию о пользователе приложение сможет запросить и получить. В настройках Yandex Identity Hub могут использоваться:

  • openid
  • email
  • profile
  • groups

Для groups можно разрешить передачу всех групп пользователя или только групп, назначенных на конкретное OIDC-приложение.

Принцип настройки простой: разрешайте только те scopes, которые действительно нужны приложению. Если запросить scope, не разрешённый в конфигурации, Authorization Server вернёт ошибку. Если уменьшить набор scopes, в ID-токене будет меньше соответствующих claims.

Подробнее о доступных scopes и пользовательских атрибутах — в документации об OIDC-приложениях.

Шаг шестой. Добавьте пользователей и группы

Чтобы пользователи могли входить во внешнее приложение, их или соответствующие группы нужно явно добавить в OIDC-приложение.

Последовательность действий мы описали в разделе «Настройте пользователей и группы» инструкции по созданию OIDC-приложения.

Шаг седьмой. Создайте секрет для Web Application

Для конфиденциального клиента создайте секрет приложения. Он понадобится при аутентификации клиента на token endpoint и при других запросах, где такая аутентификация предусмотрена.

Для SPA секрет создавать не нужно и нельзя использовать как средство защиты: клиентская часть не способна хранить его безопасно.

Готовые примеры настройки единого входа для разных приложений мы собрали в разделе «Настройка единого входа в приложения».

Как протестировать OIDC-интеграцию без собственного бэкенда

Чтобы проверить настройки и понять механику OIDC, необязательно разрабатывать приложение и разворачивать серверную часть.

На вебинаре мы выполняли запросы в Postman, но вместо него можно использовать Bruno, Insomnia или curl. Нужен инструмент для отправки HTTP-запросов и браузер, в котором пройдёт перенаправление пользователя.

Адреса authorization, token, UserInfo, JWKS и revoke endpoints доступны в конфигурации поставщика услуг на странице OIDC-приложения. Их можно получить вручную или через URL из поля OpenID Configuration. Подробнее об этих параметрах — в документации Yandex Identity Hub.

Для демонстрации можно зарегистрировать тестовый HTTPS-адрес, который проходит валидацию, но не ведёт на развёрнутый callback endpoint. Authorization code и state будут видны после перенаправления. В рабочем приложении нужно указать реальный HTTPS-адрес обработчика.

Такой ручной тест позволяет последовательно менять scopes, параметры PKCE и Redirect URI и сразу видеть, как конфигурация влияет на ответ сервера.

Как проходит Authorization Code Flow

В базовом сценарии используются два ключевых запроса: authorization request и token request. Поговорим о каждом подробнее.

Authorization request

Запрос отправляется на authorization endpoint. В нём используются такие параметры:

  • response_type=code — приложение ожидает authorization code
  • client_id — идентификатор приложения
  • scope — запрашиваемый набор scopes
  • redirect_uri — зарегистрированный адрес возврата
  • state — значение для связи ответа с запросом, инициированным приложением
  • nonce — значение, которое затем появляется в ID-токене и помогает ограничить повторное использование токена
  • code_challenge и code_challenge_method — параметры PKCE

После аутентификации пользователя Yandex Identity Hub перенаправляет браузер на Redirect URI и передаёт authorization code. Вместе с ним возвращается state, который приложение должно сопоставить с исходным значением.

В рабочем приложении параметры PKCE нужно генерировать для каждого flow. Фиксированную пару code_verifier и code_challenge можно использовать только как упрощение при демонстрации механики запросов.

Token request

Полученный authorization code приложение передаёт на token endpoint. Для Web Application запрос также содержит данные для аутентификации клиента и code_verifier, соответствующий ранее переданному code_challenge.

В ответ приложение получает token response, в котором присутствуют:

  • ID-токен
  • access-токен

Для SPA token request выполняется без client_secret, поскольку публичный клиент не проходит аутентификацию с помощью секрета. Остальная логика flow сохраняется, а PKCE остаётся обязательным.

Как работать с ID-токеном

ID-токен содержит информацию, с помощью которой приложение определяет, какой пользователь прошёл аутентификацию. Он выпускается в формате JSON Web Token, или JWT, который описан в RFC 7519.

ID-токен может включать:

  • стандартные OIDC claims
  • адрес электронной почты
  • данные профиля
  • группы пользователя
  • сведения о событии аутентификации
  • переданное ранее значение nonce

Состав claims зависит от разрешённых и запрошенных scopes.

Проверяйте подпись ID-токена

ID-токен нельзя считать достоверным только потому, что его удалось декодировать. Приложение должно проверить его подпись и выполнить остальные предусмотренные проверки токена.

В заголовке JWT есть идентификатор ключа kid. По нему приложение выбирает нужный публичный ключ из JWKS — набора JSON Web Keys. Формат ключей описан в RFC 7517.

Yandex Identity Hub может публиковать несколько ключей, поскольку ключи периодически ротируются. Если содержимое подписанного токена изменить, проверка подписи должна завершиться ошибкой.

Для чего нужен access-токен

В рассматриваемом OIDC-сценарии access-токен используется для обращения к ресурсу UserInfo. Для клиента это непрозрачная строка: её не нужно самостоятельно разбирать как ID-токен.

При запросе к UserInfo endpoint access-токен передаётся в заголовке Authorization. В ответ приложение получает атрибуты пользователя. Они могут быть похожи на данные из ID-токена, но UserInfo описывает пользователя как ресурс, тогда как ID-токен также относится к конкретному событию аутентификации.

Access-токен можно отозвать через revoke endpoint. Механизм отзыва токенов описан в RFC 7009.

Для конфиденциального клиента запрос выполняется с аутентификацией по client_id и client_secret. После успешного отзыва прежний access-токен перестаёт работать, и запрос к UserInfo с ним завершается ошибкой.

Какие ошибки показывают, что ограничения работают

При проверке интеграции полезно намеренно менять параметры и смотреть на ответ сервера. Это помогает убедиться, что конфигурация действительно применяется.

Запрошен неразрешённый scope

Если приложение запросит profile или groups, хотя они не разрешены в настройках, Authorization Server вернёт ошибку. Клиент не может расширить доступ только за счёт параметров запроса.

Не переданы параметры PKCE

Если PKCE обязателен, authorization request без code_challenge не выполнится. Если flow начат с PKCE, token request без корректного code_verifier также не должен завершиться успешно.

Redirect URI не совпадает

Адрес в authorization request должен полностью совпадать с зарегистрированным Redirect URI. Частичное совпадение или даже отличие в одном символе недопустимо.

SPA пытается использовать секрет

У Single-Page Application нет методов аутентификации клиента и секрета. Token request выполняется с client_id, но без client_secret.

Чек-лист безопасной настройки OIDC-приложения

Перед запуском интеграции проверьте следующее:

  • Выбран профиль, соответствующий архитектуре приложения.
  • При наличии серверной части используется Web Application, а обмен кода на токены выполняется на бэкенде.
  • Публичный клиент не хранит и не использует client_secret.
  • Для SPA и нативного приложения включён PKCE.
  • Redirect URI зарегистрирован заранее и совпадает с адресом в запросе полностью.
  • В рабочей среде используется HTTPS, кроме допустимых сценариев тестирования на localhost.
  • Разрешены только необходимые scopes.
  • Параметры PKCE генерируются для каждого flow.
  • Возвращённый state сопоставляется с исходным значением.
  • ID-токен не только декодируется, но и проверяется, включая проверку подписи по ключу из JWKS.
  • Access-токен используется как непрозрачная строка для обращения к UserInfo.
  • При необходимости предусмотрен отзыв access-токена через revoke endpoint.

Готовы перейти к настройке?

Создайте OIDC-приложение в Yandex Identity Hub и используйте чек-лист, чтобы проверить его конфигурацию перед подключением к рабочему приложению.

Вопросы и ответы

Какой тип OIDC-приложения выбрать, если есть бэкенд?

Для большинства приложений с серверной частью подходит Web Application. Тогда authorization code обменивается на токены на бэкенде, а клиент может аутентифицироваться с помощью client_id и client_secret.

Можно ли отключить PKCE?

Для Web Application требование PKCE можно отключить. Для Single-Page Application и Native Application PKCE обязателен. Если flow начался с параметрами PKCE, завершить его без корректного code_verifier нельзя.

Можно ли протестировать OIDC без разработки приложения?

Да. Для проверки достаточно настроить OIDC-приложение, взять адреса endpoints из Yandex Identity Hub и отправлять запросы через Postman, Bruno, Insomnia или curl.

Почему Redirect URI должен совпадать полностью?

Yandex Identity Hub проверяет Redirect URI строгим сравнением. Если адрес в запросе отличается от зарегистрированного хотя бы одним символом, запрос завершится ошибкой.

Чем ID-токен отличается от access-токена?

ID-токен содержит информацию о прошедшем аутентификацию пользователе и событии аутентификации. Access-токен предоставляет доступ к защищённому ресурсу — в вебинаре мы рассматривали сценарии с UserInfo.

Что важно запомнить

Безопасность OIDC-интеграции складывается из нескольких взаимосвязанных решений. Тип приложения определяет, может ли клиент хранить секрет и как должен использовать PKCE. Scopes ограничивают объём данных о пользователе. Redirect URI защищает маршрут возврата authorization code. state и nonce связывают запросы и токены с конкретным flow, а проверка подписи ID-токена подтверждает целостность полученных данных.

Ручная проверка flow полезна до подключения интеграции к рабочему приложению: она показывает не только успешный сценарий, но и реакцию сервера на лишний scope, отсутствие PKCE или несовпадающий Redirect URI. Благодаря этому ошибки в конфигурации можно обнаружить до разработки полной интеграции.

Как настроить безопасную OIDC-аутентификацию в Yandex Identity Hub

Войдите, чтобы сохранить пост