Неудачный опыт с SAML: как мы полтора месяца разрабатывали решение, которое пришлось отключить

У компании был портал на Active Directory с входом по логину и паролю. Бизнес решил сделать единую сквозную авторизацию через SAML 2.0. Мы выбрали пакет aacotroneo/laravel-saml2, настроили обмен с Active Directory и запустились. Но выяснилось: пользователям приходится проходить две авторизации — сначала в нашем сервисе, затем на портале. Через неделю поступили жалобы от большинства сотрудников. Позже решение отключили. Рассказываем, почему так вышло и что мы вынесли из этого опыта.

Неудачный опыт с SAML: как мы полтора месяца разрабатывали решение, которое пришлось отключить

Контекст: портал на Active Directory и наш сервис авторизации

Это история — продолжение нашего рассказа о сервисе сквозной авторизации. Напомним контекст.

У компании был портал, где работала часть сотрудников. Компьютеры находились под Active Directory. Вход в портал и на компьютеры осуществлялся по логину (не почте) и паролю.

В нашем приложении авторизации вход был другим:

  • email + пароль;

  • номер телефона + SMS-код;

  • комбинированная многофакторная авторизация.

Бизнес решил: нужно сделать единую сквозную авторизацию через Active Directory и SAML 2.0. Идея логичная — сотрудники должны входить в сервисы через свой рабочий аккаунт, без лишних паролей.

Наша команда впервые столкнулась с такой задачей. Ранее мы использовали SAML только в связке с Google.


Что такое SAML 2.0

SAML 2.0 — это XML-протокол для обмена данными аутентификации между Identity Provider (IdP) и Service Provider (SP) .

Как это обычно работает:

  1. Пользователь пытается зайти в сервис (SP).

  2. Сервис перенаправляет его на Identity Provider (в нашем случае — портал на Active Directory).

  3. Пользователь вводит логин и пароль на стороне IdP.

  4. IdP проверяет данные и отправляет сервису SAML-assertion — XML-документ с подтверждением личности.

  5. Сервис доверяет IdP и пускает пользователя.

Ключевой принцип: аутентификация происходит на стороне IdP. Сервис не хранит пароль пользователя, он доверяет assertion от IdP.

Именно в этом и крылась проблема, которую бизнес не увидел.


Наша реализация: пакет и настройка

Мы изучили готовые пакеты, чтобы не писать всю обвязку с нуля. Выбрали aacotroneo/laravel-saml2 .

Почему этот пакет:

  • Содержит все необходимые роуты (metadata, ACS, SLS).

  • Позволяет настроить обмен через XML-конфигурации.

  • Даёт возможность подвязать SAML к нашей логике с ветвлением сценариев.

Важное ограничение: внешним клиентам SAML был не нужен. Его цель — только единый вход для внутренних сотрудников. Поэтому мы настроили ветвление: если пользователь — внутренний, его перенаправляет на портал; если внешний — авторизация идёт по обычной схеме.

Сторона разработки Active Directory доработала под нас XML-формат обмена. Мы запустились.


Как это работало: технические детали

Опишем полный сценарий входа для внутреннего сотрудника.

Шаг 1. Первичная идентификация в нашем сервисе

Пользователь заходил на страницу авторизации нашего сервиса и вводил email + пароль или номер телефона. Это был первый фактор.

Зачем это было нужно: мы должны были определить, нужно ли ему заходить через SAML. Если пользователь — внутренний сотрудник, система понимала это и перенаправляла его на портал.

Шаг 2. Редирект на портал с XML-телом

После первичной идентификации мы отправляли пользователя на портал с XML-телом объекта пользователя. Портал получал данные и показывал свою форму входа.

Шаг 3. Ввод логина и пароля портала

Пользователь вводил логин (не почту) и пароль от портала. Это была вторая авторизация.

Шаг 4. SAML-ответ и вход

Портал (IdP) проверял данные и отправлял SAML-assertion обратно в наш сервис. Мы валидировали assertion и завершали вход.

Сессия жила в течение рабочего дня сотрудника.

С технической точки зрения всё было настроено корректно. SAML работал. Но с точки зрения пользовательского опыта — это был провал.


Проблема: две авторизации вместо одной

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

Что происходило на практике:

Чтобы войти в любой из сервисов, сотруднику нужно было:

  1. Авторизоваться в нашем сервисе авторизации (email/пароль или телефон).

  2. Ввести логин и пароль портала.

Две разные авторизации. Два разных набора credentials.

Бизнес при решении о внедрении SAML предполагал, что авторизация будет в одной точке — данные вводятся единожды. Но этого не произошло.


Почему так вышло: ограничение, которое не услышали

Наша команда и архитектор донесли ограничение SAML до бизнеса ещё до начала разработки.

Суть ограничения:

SAML работает так, что аутентификация происходит на стороне Identity Provider (портала). Но чтобы дойти до портала, пользователь должен сначала как-то идентифицироваться в нашем сервисе — чтобы мы поняли, что он внутренний сотрудник и его нужно перенаправить на IdP.

Это создаёт две точки входа:

  • наш сервис (первичная идентификация);

  • портал (основная аутентификация через SAML).

Мы предупредили, что понадобится проходить две разные авторизации. Бизнес это не услышал.

Это не была техническая ошибка. Это было недопонимание между бизнесом и технической реальностью. Бизнес хотел «одну точку входа», но SAML в данной архитектуре этого не давал.


Результат: полтора месяца разработки и отключение

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

Что это дало:

  • Опыт работы с SAML 2.0 и пакетом aacotroneo/laravel-saml2.

  • Понимание ограничений протокола в контексте пользовательского опыта.

  • Урок о важности донесения технических ограничений до бизнеса на языке бизнеса.

Что это стоило:

  • Время команды — полтора месяца.

  • Негатив сотрудников — неделя жалоб.

  • Необходимость откатывать решение. Благо гибкая конфигурация, которую мы реализовали позволила быстро откатить решение.


Что мы вынесли из этой истории

1. SAML — это не «одна кнопка входа»

SAML решает задачу федеративной аутентификации, но не устраняет необходимость в первичной идентификации, если ваш сервис должен определить, куда направить пользователя. Если бизнес хочет «одну точку входа», нужно либо:

  • делать портал единственной точкой входа (пользователь идёт сразу на портал);

  • или принять две авторизации как данность.

2. Технические ограничения нужно доносить на языке бизнеса

Мы предупредили. Но, видимо, недостаточно наглядно. Урок: когда объясняете ограничение, покажите пользовательский сценарий, а не техническую схему. «Пользователь введёт пароль дважды» — понятнее, чем «SAML требует первичной идентификации на стороне SP».

3. «Не услышали» — это тоже ответственность команды

Если бизнес не услышал — значит, мы не смогли объяснить. Это неприятный, но важный вывод. Техническая правота не спасает от провала, если заказчик не понял последствий.

4. Неудачный опыт — тоже опыт

Мы получили редкий практический навык: настройка SAML с Active Directory, работа с aacotroneo/laravel-saml2, понимание XML-обмена. В следующий раз, когда возникнет задача с SAML, мы будем знать, как это делать — и какие грабли обходить.


Технические детали SAML, которые стоит знать

Для тех, кто столкнётся с похожей задачей:

Identity Provider (IdP) — сторона, которая аутентифицирует пользователя. В нашем случае — портал на Active Directory.

Service Provider (SP) — сторона, которая доверяет IdP. В нашем случае — наш сервис авторизации.

SAML Assertion — XML-документ, который IdP отправляет SP. Содержит подтверждение личности пользователя и атрибуты (email, роли и т.д.) .

ACS (Assertion Consumer Service) — endpoint на стороне SP, куда IdP отправляет assertion. В пакете aacotroneo/laravel-saml2 этот роут создаётся автоматически .

Metadata — XML-файл с настройками SP или IdP. Содержит URL, сертификаты и другие параметры для обмена. В пакете metadata доступна по роуту /{idpName}/metadata .

Сложности SAML, которые стоит учитывать:

  • сложная настройка (XML, метаданные, сертификаты);

  • сложная отладка (ошибки в XML-подписях не всегда очевидны);

  • ограниченная гибкость в пользовательских сценариях .


Заключение

Эта история — про то, что технически корректное решение может быть провальным с точки зрения пользователя.

SAML работал. Но сотрудники получили две авторизации вместо одной — и справедливо возмутились. Мы предупреждали, но нас не услышали. В итоге — полтора месяца разработки и отключение.

Это был важный урок для нашей команды. И, надеемся, полезный для тех, кто рассматривает SAML для своей инфраструктуры.

Porozmawiajmy o projekcie

Opowiedz o zadaniu — wycenimy w kilka dni

Kontakt