open atlas
↑ К треку
Основы безопасности SECF · 03 · 04

SSO и федерация

SSO федерирует вход к IdP, но SP по-прежнему владеет проверкой на входе (подпись, issuer, audience, срок) и сносом сессии на выходе — а отзыв в федерации всегда лишь согласован в конечном счёте.

SECF Senior ◷ 16 min
Уровень
ОсновыJuniorMiddleSenior

Клиент заводит тикет: подрядчик, которого он уволил в корпоративном каталоге неделю назад, всё ещё залогинен в вашем SaaS и скачивает отчёты. Вы смотрите в код — вход работает, кнопка «Войти через ваш IdP» зелёная, федерация настроена ровно так, как сказано в документации вендора. И всё же отключённый аккаунт гуляет по вашему приложению семь дней спустя. Ничто не «сломано» в смысле выброшенной ошибки: IdP аутентифицировал этого человека в день ноль, ваше приложение этому поверило, выпустило сессию — и забыло, что IdP существует. Эта дыра — между тем, как личность отзывают выше по потоку, и тем, как ваше приложение это замечает, — и есть та часть SSO, о которой туториал по интеграции никогда не упоминает, а разбор инцидента всегда находит. «Мы используем SSO» — это начало разговора об аутентификации, а не его конец.

К концу урока вы будете точно знать, что IdP делает за вас, чего он подчёркнуто не делает, какие четыре проверки SP по-прежнему обязан выполнять над каждым токеном, и почему отзыв в федерации согласован в конечном счёте, а не мгновенен.

Что федерация на самом деле делегирует — и что нет

Single sign-on позволяет пользователю аутентифицироваться один раз у центрального провайдера идентичности (IdP) — Okta, Entra ID, Google Workspace, собственный каталог клиента — и затем получать доступ ко многим поставщикам сервиса (SP): вашим приложениям. Федерация — это договорённость о доверии, которая делает IdP одной организации авторитетом, которому ваш SP будет верить. Два доминирующих протокола — SAML (XML-утверждения, с упором на корпоративный сектор) и OpenID Connect / OIDC (слой идентичности на основе JWT поверх OAuth 2.0). Разные форматы на проводе, одна форма: IdP аутентифицирует пользователя и передаёт вашему SP подписанное утверждение — SAML-assertion или OIDC ID token, — которое говорит «этот субъект аутентифицировался, вот его claims».

Вот что именно делегирует федерация: сам акт аутентификации пользователя. IdP выполняет проверку пароля, запрос MFA, церемонию passkey; вы никогда не видите учётные данные. Чего федерация не делегирует — это всё вокруг этого утверждения. SP по-прежнему обязан проверить, что утверждение подлинно и предназначено ему, решить, как долго доверять ему локально, и снести это локальное доверие, когда пользователя больше нет. Ментальная модель, ведущая к инцидентам, — «мы отдали аутентификацию IdP на аутсорс». Вы отдали проверку учётных данных. Проверка, срок жизни сессии и выход по-прежнему ваши.

Четыре проверки, которыми SP по-прежнему владеет над каждым токеном

Когда ID token приходит, «IdP его подписал» — необходимо, но и близко не достаточно. Senior относится к проверке как к четырём отдельным воротам, и пройти три из них — всё равно дыра.

  1. Подпись — подтвердить, что токен подписан тем IdP, которому вы доверяете, опубликованным ключом IdP (эндпоинт JWKS для OIDC, сертификат из метаданных SAML). Это отвечает на вопрос «произвёл ли это мой доверенный IdP?». Критично: зафиксируйте алгоритм вне канала на согласованном при настройке федерации (например, RS256) и никогда не доверяйте полю alg в собственном заголовке токена — классическая атака путаницы алгоритмов понижает RS256 до HS256 и подписывает публичным ключом IdP (который по определению публичен), используемым как секрет HMAC, и наивный верификатор это принимает.
  2. Issuer (iss) — подтвердить, что токен пришёл от конкретного IdP, с которым вы федерировались, а не просто от какого-то IdP, чей ключ вы случайно получили. Без этой проверки токен, выпущенный любым issuer, до которого вы можете достучаться, пропускается.
  3. Audience (aud) — подтвердить, что токен выпущен для вас. Claim audience привязывает токен к конкретному client ID SP. Это отвечает на другой вопрос, чем подпись: «было ли это произведено для меня?». В федерации с несколькими SP это огромная разница — подлинный, корректно подписанный токен, выпущенный для соседнего приложения SP-A, можно реплейнуть на SP-B, и если SP-B пропускает проверку audience, он принимает его как валидный вход.
  4. Срок (exp) — подтвердить, что токен ещё в окне валидности. Перехваченный токен без проверки срока работает вечно.

Подпись отвечает «кто подписал»; issuer, audience и срок — «от кого, для кого и всё ещё ли валиден?». Это четыре проверки, а не одна.

Частая ошибка

SAML-аналог путаницы алгоритмов — XML Signature Wrapping (XSW). Изъян — это баг порядка: код читает личность пользователя из «первого найденного <Subject>», а затем отдельно спрашивает библиотеку «валидна ли подпись документа?» — и оба шага успешны. Атакующий внедряет второй <Subject>, который читает приложение, тогда как валидная подпись по-прежнему покрывает исходный элемент. Проверить, что какая-то подпись валидна, не то же самое, что проверить, что она покрывает те самые байты, на которых вы действовали. Фикс — использовать проверенную SAML-библиотеку правильно, чтобы валидация подписи и извлечение личности были связаны с одним и тем же элементом — никогда не писать разбор XML вручную и никогда не читать личность ни из чего, кроме подписанного, проверенного узла.

Разрыв деактивации: федерация федерирует вход, а не выход

Это и есть сбой из Hook, и он структурный, а не опечатка. Утверждение IdP — это факт на момент времени: «этот субъект аутентифицировался в 09:14 в день ноль». Ваш SP проверяет его и выпускает локальную сессию — и эта сессия теперь ваша, отвязанная от IdP. Когда клиент отключает пользователя в день ноль, ничто не проталкивает это изменение в ваше хранилище сессий. Вход был pull (SP вытянул утверждение, когда пользователь пришёл); деактивация требует push (IdP сообщает SP «снеси это»), а базовый поток входа такого канала не имеет. Если ваша локальная сессия живёт 30 дней, отключённый пользователь продолжает работать до 30 дней, потому что ему не приходится возвращаться через IdP — который теперь отказал бы ему.

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

  • Короткие сроки жизни сессий SP (минуты-несколько часов, не дни), чтобы деактивированного пользователя скоро отправило обратно через IdP и отказало. Это ограничивает рутинный устаревший доступ длиной сессии.
  • Активный канал отзыва там, где это позволяет протокол: OIDC back-channel logout или SAML Single Logout, чтобы поддерживающий это IdP мог вызвать ваш logout-эндпоинт и немедленно снести сессии — рассматривается как best-effort, потому что не каждый IdP это реализует, а сети отказывают.
  • Step-up перепроверка для чувствительных действий (платежи, смена ролей, экспорт данных): перепроверяйте IdP или требуйте свежий auth_time в момент действия, чтобы пути с наибольшим ущербом получили почти реальное время без вызова IdP на каждом чтении.
  • Прямо укажите остаточное окно в документах безопасности и контракте с клиентом: разрыв между отключением выше по потоку и истечением сессии SP ненулевой. Это владеемое, сообщённое свойство — а ужесточение срока сессии это ручка, которую клиент может попросить повернуть.
ЗонаЧем владеет IdPЧем по-прежнему владеет SP
Проверка учётных данныхПароль, MFA, церемония passkeyНичем — полностью делегировано
Доверие к токенуПодписывает утверждение / ID tokenПроверить sig, iss, aud, exp — зафиксировать алгоритм
Локальная сессияНичем после редиректаСрок жизни, кука, где живёт истина
ОтзывОтключает пользователя; может протолкнуть logoutОграничить окно; провести back-channel logout
Сбой проверки подписипутаница alg (JWT) / XML Signature Wrapping (SAML)

Как senior рассуждает о любой интеграции «Войти через…»

Сделайте это постоянным вопросом для каждой настраиваемой федерации: когда эту личность отзывают выше по потоку, сколько проживёт моя сессия ниже по потоку — и владеемо ли и сообщено ли это окно? Затем прогоните фиксированный чек-лист на входе и на выходе: зафиксированные issuer и ключ, audience, ограниченный этим SP, подпись с зафиксированным алгоритмом, проверка срока, короткий срок жизни сессии, проведённый back-channel logout там, где IdP его поддерживает, и step-up перепроверка на чувствительных действиях. Считайте отзыв согласованным в конечном счёте по умолчанию. SP никогда не перестаёт владеть проверкой на входе и сносом на выходе — федерация переместила проверку учётных данных, а не вашу ответственность за этот шов.

Выбери лучший вариант

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

Викторина

Подпись OIDC ID token проверяется против JWKS провайдера IdP, и срок не истёк. Почему этого всё ещё недостаточно, чтобы залогинить пользователя?

Викторина

Почему нужно фиксировать ожидаемый алгоритм подписи вне канала, а не доверять полю alg в заголовке токена?

Расставь шаги по порядку

Расставь по порядку шаги корректного превращения OIDC-колбэка в доверенную локальную сессию:

  1. 1 Обменять authorization code на ID token на token-эндпоинте IdP
  2. 2 Проверить подпись против JWKS провайдера IdP с алгоритмом, зафиксированным вне канала (например, RS256)
  3. 3 Проверить, что iss — твой IdP, aud — client ID этого SP, а exp в будущем
  4. 4 Выпустить короткоживущую локальную сессию и провести back-channel logout, чтобы IdP мог её снести
Вспомните перед уходом
  1. 01
    Федерация делегирует аутентификацию IdP. Назови точно, чем по-прежнему владеет SP и почему.
  2. 02
    Объясни разрыв деактивации и как ты его ограничиваешь, не делая свою доступность зависимой от IdP клиента.
Итог

Single sign-on позволяет пользователю аутентифицироваться один раз у центрального IdP и достичь многих SP, по SAML или OIDC — но федерация делегирует только проверку учётных данных. IdP выполняет церемонию пароля, MFA или passkey и передаёт вашему SP подписанное утверждение; всё остальное остаётся вашим. На входе SP владеет четырьмя отдельными воротами проверки: подпись (с алгоритмом, зафиксированным вне канала, никогда не доверяя собственному полю alg токена, иначе вы приглашаете путаницу алгоритмов RS256→HS256; SAML-аналог — XML Signature Wrapping), issuer, audience (чтобы токен, выпущенный для соседнего SP, не реплейнулся) и срок — потому что «IdP это подписал» отвечает, кто подписал, а не от-кого-для-кого-и-всё-ещё-ли-валиден. На выходе SP владеет сносом, и именно здесь SSO тихо ломается: федерация федерирует вход (pull), но не выход (push), поэтому, когда личность отзывают выше по потоку, ничто не доходит до вашего хранилища сессий, и долгоживущая локальная сессия держит отключённого пользователя внутри вашего приложения. Вы не можете сделать внешний отзыв мгновенным, поэтому вы ограничиваете окно — короткие сроки жизни сессий, OIDC back-channel logout или SAML Single Logout как best-effort, step-up перепроверка на чувствительных действиях — и заявляете остаточный разрыв, а не делаете вид, что он нулевой. Постоянный вопрос для каждой интеграции «Войти через…»: когда эту личность отзывают выше по потоку, сколько проживёт моя сессия ниже по потоку, и владеемо ли и сообщено ли это окно?

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 6 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.