awesome-everything EN
↑ Обратно к восхождению

Безопасность

OAuth/OIDC: собери и проверь защищённый логин

Суть Практический проект — собери защищённый OIDC-логин и sender-constrained API, затем проведи аудит по чеклисту полного набора юнита и докажи каждую обязательную проверку adversarial-тестом.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать про CVE в OAuth — не то же самое, что доказать, что в твоей реализации их нет. Собери небольшой, но полный OIDC-логин на реальном authorization server, sender-constrain-ни API и затем сам атакуй каждую обязательную проверку — только adversarial-тест, падающий на сломанном пути, доказывает, что проверка действительно есть.

Цель

Преврати модель полного набора юнита в работающую, проверенную систему: authorization code с PKCE, полная валидация id_token с обработкой ротации JWKS, ротация refresh token с обнаружением replay, вызовы API с привязкой DPoP и дашборд наблюдаемости — каждая защищена тестом, доказывающим, что проверка держит.

Проект
0 из 9
Цель

Собери защищённый OIDC-логин и sender-constrained защищённый API на реальном authorization server (Auth0, Okta, Keycloak или Authentik), затем проведи аудит безопасности, доказывающий каждую обязательную проверку adversarial-тестом, который незащищённый путь провалил бы.

Требования
Критерии приёмки
  • Adversarial-набор тестов, где каждый тест прогоняет один сломанный путь и отклоняется: повторённый authorization code (PKCE), несовпадающий state, подделанный или alg=none id_token, id_token с неверным aud, повторно использованный refresh token (срабатывает обнаружение replay) и вызов DPoP с отсутствующим или неверным proof.
  • Продемонстрированный сценарий ротации ключа JWKS: ротируй ключ подписи IdP (или эмулируй новый kid) и покажи, что логин продолжает работать, потому что обновление при промахе кэша тянет новый ключ вместо 401.
  • Проверка хранения токенов: access token доказуемо отсутствует в localStorage, а refresh token лежит в куке httpOnly, недоступной JS (или эквивалент платформы).
  • Дашборд показывает, что refresh_replay_detected_total увеличивается ровно один раз при прогоне теста на повторное использование refresh token, а id_token_validation_failure_total растёт по причине на каждый отклонённый тест id_token.
  • Одностраничный отчёт аудита, сопоставляющий каждую обязательную проверку юнита (PKCE, точный redirect, восемь проверок id_token, ротация refresh, sender-constraint, валидация аудитории) с тестом, который её доказывает.
Senior-стретч
  • Добавь PAR (Pushed Authorization Requests), чтобы параметры authorize никогда не попадали в URL браузера, и покажи, что их нет в истории и заголовках referrer.
  • Добавь token introspection на высокочувствительный write-эндпоинт с кэшем introspection 30 с и продемонстрируй, что токен, отозванный на IdP, отклоняется внутри окна кэша, пока локальная валидация JWT всё ещё обслуживает read-путь.
  • Добавь RFC 8707 Resource Indicators, чтобы токен, выпущенный для API-A, отклонялся API-B, и включи регрессионный тест, что aud равный other-api отвергается.
  • Прогони тот же логин на втором authorization server (например, замени Keycloak на Auth0) и задокументируй, какие проверки потребовали изменения конфигурации, а какие были переносимы.
Итог

Это цикл, который ты запускаешь на каждой реальной интеграции OAuth: собрать поток с PKCE, полностью валидировать id_token с закреплённым алгоритмом и обновлением JWKS при промахе кэша, ротировать refresh token с обнаружением replay, sender-constrain-ить API через DPoP, хранить токены по модели угроз клиента и подключить наблюдаемость, вскрывающую компрометацию. Затем проверить adversarial — проверка, которую ты не атаковал, это проверка, которую ты не доказал. Сделав это раз на маленькой системе, ты превращаешь дисциплину полного набора в мышечную память для production.

Продолжить восхождение ↑Ловушки безопасности JWT: путаница alg, отсутствие отзыва и где утекают токены
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.