OpenID Connect под нагрузкой: проверка корпоративного сервера

📋 Кратко

Корпоративный сервер идентификации должен выдерживать не только обычный вход, но и массовое обновление сессий, проверку ключей и сбои зависимостей. В статье разбираем безопасную методику нагрузочной проверки OpenID Connect: от разделения идентификации, аутентификации и авторизации до критериев остановки, журналирования и контроля утечек данных в токенах.

⏱ 10 минут чтениясложность

Корпоративный сервер идентификации становится общей точкой входа для приложений, API и рабочих сервисов. Его сбой блокирует сразу несколько процессов. Поэтому проверка под нагрузкой нужна до масштабного запуска.

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

Главная мысль: проверяйте OIDC-сервер как связку компонентов. В неё входят браузерный вход, выдача токенов, каталог пользователей, база данных, кэш, хранилище ключей и резервный узел.
Идентификация и авторизация требуют разных проверок
Идентификация и авторизация требуют разных проверок

🔍 Что именно проверяет OpenID Connect

OpenID Connect, или OIDC, проверяет личность пользователя при входе. Он обычно работает поверх OAuth 2.0. OAuth отвечает за доступ к ресурсам, а OIDC добавляет подтверждение личности.

Безопасный вход состоит из последовательных проверок
Безопасный вход состоит из последовательных проверок

Эти задачи нельзя смешивать. Идентификация отвечает на вопрос «кто это». Аутентификация проверяет утверждение пользователя. Авторизация определяет, что ему разрешено.

После входа приложение получает токены. ID-токен подтверждает личность пользователя. Токен доступа показывает права для обращения к ресурсу. Ошибка в таком разделении приводит к неверным решениям в приложении.

OIDC поддерживает единый вход. Он также помогает централизовать многофакторную аутентификацию и условный доступ. Это снижает число разрозненных паролей в корпоративной среде.

Сначала составьте карту ролей. Укажите сервер идентификации, приложение, пользователя, API и каталог. Затем отдельно опишите, какой токен используется на каждом шаге.

🧭 Как выглядит путь пользователя

Проверка начинается с Discovery. Клиент получает сведения о сервере и его возможностях. На этом этапе важно сравнить опубликованные сведения с реальным поведением конечных точек.

Реальная нагрузка требует разных сценариев поведения
Реальная нагрузка требует разных сценариев поведения

Затем пользователь проходит авторизацию. Клиент отправляет его на сервер идентификации. После успешного входа сервер возвращает код авторизации.

Клиент обменивает код на токены. В безопасном сценарии код используется один раз. Повторное принятие кода создаёт риск повторной выдачи токенов.

После этого клиент проверяет ID-токен. Он сверяет издателя, аудиторию, срок действия, состояние запроса и одноразовое значение. Эти проверки должны работать одинаково при низкой и высокой нагрузке.

Отдельно проверяйте запрос к UserInfo. Он может вернуть сведения о пользователе. Набор полей должен соответствовать разрешённому запросу.

Начните тест с одного полного входа. Запишите все запросы и ответы в обезличенном виде. Только после этого добавляйте параллельных пользователей.

🛠️ Какие сценарии нагрузки нужно включить

Один сценарий входа не отражает реальную работу. Пользователи входят неравномерно. После массового начала рабочего дня сервер получает короткий резкий всплеск.

Предел системы заметен по хвостам задержек
Предел системы заметен по хвостам задержек

Первый сценарий проверяет Discovery. Клиенты запрашивают сведения о сервере. Такой трафик можно отделить от пользовательского входа и оценить влияние кэширования.

Второй сценарий проверяет переход на страницу авторизации. Он включает проверку сессии и действия тестового пользователя. Реальные учётные записи в такой проверке не применяются.

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

Четвёртый сценарий проверяет обновление токена. Он показывает, как сервер ведёт себя при одновременном обновлении множества сессий. Этот всплеск часто отличается от утреннего входа.

Пятый сценарий обращается к набору ключей JWKS. Клиент использует его для проверки подписи токена. При ротации ключей нужно проверить получение нового набора.

Шестой сценарий проверяет выход из сессии. Он показывает нагрузку на хранилище сессий и связанные конечные точки. Сценарий важен для приложений с централизованным управлением входом.

СценарийЧто измерятьЧто считать проблемой
DiscoveryЗадержку и число ошибокРост задержки при повторных запросах
АвторизацияВремя ответа и ошибки сессииСбои при росте параллельных входов
Обмен кодаВремя выдачи токеновПовторное принятие кода
Обновление токенаЗадержку и пропускную способностьОчереди и массовые отказы
JWKSВремя получения ключейОшибки после ротации
ВыходВремя завершения сессииСохранение действующей сессии

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

📊 Какие метрики показывают предел

Пропускная способность показывает объём успешно обработанных операций. Но одна цифра не описывает качество сервиса. Её нужно смотреть вместе с задержками и ошибками.

Безопасный контур защищает пользователей и секреты
Безопасный контур защищает пользователей и секреты

Измеряйте задержки p50, p95 и p99. p50 показывает типичный ответ. p95 показывает опыт большинства пользователей. p99 помогает увидеть редкие, но тяжёлые задержки.

Отдельно фиксируйте долю ошибок. Разделяйте ошибки клиента, сервера и зависимостей. Иначе команда не поймёт, где возникает сбой.

Для токенов измеряйте время выдачи и обновления. Для Discovery и JWKS измеряйте время ответа при попадании в кэш и без него. Сравнение показывает пользу кэширования.

Одновременно наблюдайте за процессором и памятью. Проверяйте базу данных, каталог пользователей и внешние сервисы. Если сервер идентификации выглядит свободным, это ещё не означает отсутствие узкого места.

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

Минимальный набор метрик: пропускная способность, p50, p95, p99, доля ошибок, время выдачи токена, время обновления, загрузка процессора, память, база данных и каталог пользователей.

Заранее установите целевые значения для каждой метрики. Не называйте тест успешным при одной хорошей средней задержке. Сначала добавьте в отчёт p95, p99 и долю ошибок.

⚙️ Как подготовить безопасный контур

Нагрузочная проверка проходит в отдельной тестовой среде. Она не должна влиять на продуктивных пользователей. Перед стартом зафиксируйте владельца контура и время теста.

Надёжность определяется предсказуемым поведением отказов
Надёжность определяется предсказуемым поведением отказов

Создайте тестовые учётные записи. Не используйте настоящие пароли, телефоны и адреса. Данные в профиле должны быть искусственными и минимальными.

Заранее согласуйте профиль нагрузки. Укажите число виртуальных пользователей, темп роста и длительность каждого этапа. Отдельно опишите допустимые ошибки.

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

Журналируйте результаты, но не записывайте токены целиком. В логах не должны появляться секреты, коды авторизации и лишние персональные данные. Для анализа используйте идентификаторы тестовых операций.

Проверьте синхронизацию времени на всех узлах. Разница времени влияет на срок действия токена и проверку одноразовых значений. Ошибка особенно заметна при распределённой нагрузке.

Перед началом убедитесь, что тестовые клиенты используют правильный redirect_uri. Также проверьте state и nonce. После этого составьте короткий план отката и остановки генератора нагрузки.

🔐 Как проверить токены и защитные проверки

Сервер должен выдавать только нужные сведения. Избыточные поля в ID-токене увеличивают последствия утечки. Особенно опасны телефон, адрес и другие персональные данные.

Готовность подтверждают нагрузка корректность и восстановление
Готовность подтверждают нагрузка корректность и восстановление

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

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

Проверяйте издателя, аудиторию и срок действия токена. Клиент должен принимать токен только от ожидаемого сервера. Он также должен проверять, для него ли предназначен токен.

Проверяйте state и nonce на каждом входе. Эти значения связывают ответ с начатым запросом. Их отсутствие или неверная проверка ломает защитную логику потока.

Проверяйте redirect_uri на точное соответствие зарегистрированному адресу. Нельзя принимать произвольный адрес из запроса. Любое расхождение должно завершаться отказом.

Проверяйте срок действия и подпись после ротации ключей. Набор JWKS должен обновляться предсказуемо. Старые ключи нельзя удалять так, чтобы действующие токены внезапно переставали проверяться.

Составьте таблицу полей для каждого клиента. Укажите, где появляется каждое поле: в ID-токене, UserInfo или нигде. Затем повторите проверку во время нагрузки.

🛡️ Как проверить зависимости и отказы

Сервер идентификации редко работает в одиночку. Он зависит от базы данных, каталога пользователей, кэша и хранилища ключей. Каждый компонент меняет результат нагрузочного теста.

Сначала проверьте недоступность базы данных. Сервер должен быстро вернуть понятную ошибку. Он не должен зависать и создавать бесконечную очередь запросов.

Затем остановите тестовый каталог пользователей. Проверьте вход, обновление токена и выход. Для каждого шага должен существовать ожидаемый безопасный результат.

Отдельно отключите кэш. Сравните задержки и загрузку зависимостей. Так становится видно, не превращается ли кэш в единственную точку отказа.

Проверьте хранилище ключей. Сервер не должен выдавать токены с непредсказуемой подписью. Ошибка должна попадать в мониторинг без раскрытия секретов.

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

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

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

Проводите отказы по одному. Не отключайте сразу базу и каталог. Иначе команда не определит причину ошибки.

🚀 Как наращивать нагрузку без искажения результата

Начинайте с базового прогона. Один тестовый клиент проходит все шаги. Команда проверяет логи, токены и итоговое состояние сессии.

Затем увеличивайте нагрузку ступенями. После каждой ступени делайте паузу для анализа. Резкий переход к максимальному уровню скрывает момент появления проблемы.

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

Не смешивайте все операции в равной пропорции. В реальной среде вход, обновление и проверка ключей встречаются по-разному. Профиль должен отражать ожидаемую архитектуру компании.

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

После каждого этапа сохраняйте конфигурацию и графики. Отмечайте изменение версии сервера и настроек. Без этого сравнение результатов становится ненадёжным.

Не используйте нагрузочный тест как проверку устойчивости чужих систем. Он проходит только в согласованном контуре. Продуктивный адрес исключается из конфигурации генератора.

Зафиксируйте точку, где p95 и p99 выходят за целевые значения. Она важнее формального максимума запросов. Именно на этом уровне пользователи начинают замечать проблему.

🧪 Как использовать внешний conformance-тест

Нагрузочный тест отвечает на вопрос о производительности. Но он не подтверждает полное соответствие протоколу. Для этого нужен отдельный функциональный conformance-тест.

Официальный conformance-suite OpenID Foundation можно запустить локально. Он доступен без заявки на сертификацию. В описанном варианте suite работает как Java-приложение в контейнерах.

В его состав входят сервер тестов, nginx и MongoDB. Suite выступает клиентом. Он регистрирует приложения у сервера, запускает потоки, проверяет ответы и сопоставляет их со спецификацией.

Такой подход находит ошибки, которые не видны в обычных проверках. Разработчик тестирует то, о чём уже знает. Внешний тест ищет расхождения с правилами протокола.

Один из важных классов ошибок связан с лишними утверждениями. Поле может попасть не в тот токен. Discovery может обещать функцию, которой нет на конечной точке.

Отдельно проверяйте одноразовость кода. Гонка при обработке может привести к повторному принятию authorization code. Это функциональная ошибка, а не показатель пропускной способности.

Сначала проведите conformance-тест на малой нагрузке. После исправлений повторите его на стабильном стенде. Только затем связывайте результаты с нагрузочным профилем.

✅ Как оформить критерии приёмки

Результат должен быть понятен не только инженеру по производительности. В отчёте укажите контур, версию сервера и состав зависимостей. Также добавьте время запуска и профиль нагрузки.

Для каждого сценария запишите целевую пропускную способность. Укажите допустимые p95 и p99. Отдельно задайте предел доли ошибок.

Добавьте критерии для токенов. Код должен приниматься один раз. Клиент должен отклонять неверные issuer, audience, state, nonce, redirect_uri и срок действия.

Опишите поведение при отказах. Укажите результат при недоступной базе, каталоге, кэше, хранилище ключей и резервном узле. Для каждого случая нужен наблюдаемый сигнал в мониторинге.

Проверьте журналы после теста. В них не должно быть полных токенов, секретов и лишних персональных данных. При этом журналы должны позволять связать ошибку с тестовой операцией.

Отдельной строкой укажите состояние пользователей. Продуктивные пользователи не должны попадать в тест. Тестовые учётные записи нужно отключить после завершения работ.

Критерий «сервер не упал» слишком слабый. Успешный результат включает задержки, ошибки, корректность токенов и восстановление после отказа. Только такая проверка показывает реальную готовность.

Прямо сейчас создайте шаблон отчёта из четырёх частей: нагрузка, метрики, корректность протокола и отказы. Заполняйте его после каждого прогона.

📌 Что проверить перед запуском

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

Подготовьте тестовые профили с минимальными данными. Проверьте, какие поля появляются в ID-токене и UserInfo. Лишние поля уберите до нагрузки.

Сверьте настройки времени на всех узлах. Проверьте состояние базы, каталога, кэша и хранилища ключей. Зафиксируйте доступность резервного узла.

  • Согласуйте профиль и длительность нагрузки.
  • Назначьте критерии остановки.
  • Настройте сбор p50, p95 и p99.
  • Разделите ошибки клиента, сервера и зависимостей.
  • Запретите запись токенов в журналы.
  • Проведите базовый прогон до ступенчатого роста.
  • После нагрузки повторите функциональные проверки.

OpenID Connect под нагрузкой нужно проверять как протокол и как инфраструктуру. Производительность без корректности токенов создаёт ложное чувство готовности. Корректный вход без проверки отказов также не защищает бизнес-процессы.

Итог: безопасная проверка сочетает изолированный контур, тестовые записи, ступенчатую нагрузку, измеримые критерии, контроль зависимостей и отдельную проверку соответствия OIDC.

Сохраните исходные настройки и результаты каждого прогона. Так команда видит динамику после изменений. Это помогает поддерживать сервер идентификации готовым к реальной нагрузке.

📚 Читайте также

📖 Термины

IAM (Identity and Access Management) · MFA · OAuth · Криптография

🔗 Источники