Złe doświadczenia z SAML: jak opracowaliśmy rozwiązanie przez półtora miesiąca, które musiało zostać wyłączone
Firma miała portal oparty na Active Directory i chciała wdrożyć jednokrotne logowanie przez SAML 2.0. Zintegrowaliśmy pakiet `aacotroneo/laravel-saml2`, ale użytkownicy musieli logować się dwukrotnie — w naszym serwisie i na portalu. Po tygodniu skarg większości pracowników rozwiązanie zostało wyłączone. Opowiadamy, dlaczego tak się stało i czego nas to nauczyło.
Kontekst: portal oparty na Active Directory i nasz system uwierzytelniania
To kolejna część naszej historii o budowie systemu uwierzytelniania SSO. Przypomnijmy kontekst.
W firmie działał portal, z którego korzystała część pracowników. Komputery były zarządzane przez Active Directory. Logowanie do komputerów i portalu odbywało się za pomocą loginu (nie adresu e-mail) i hasła.
W naszej aplikacji uwierzytelnianie działało inaczej. Użytkownicy mogli logować się za pomocą:
-
adresu e-mail i hasła;
-
numeru telefonu i kodu SMS;
-
kombinacji kilku czynników uwierzytelniania.
Biznes podjął decyzję: należy wdrożyć jednolite logowanie za pośrednictwem Active Directory z wykorzystaniem SAML 2.0. Pomysł wydawał się logiczny — pracownicy powinni uzyskiwać dostęp do usług za pomocą kont służbowych, bez konieczności pamiętania dodatkowych haseł.
Nasz zespół po raz pierwszy mierzył się z takim zadaniem. Wcześniej korzystaliśmy z SAML wyłącznie w integracji z Google.
Czym jest SAML 2.0?
SAML 2.0 to protokół oparty na XML, służący do wymiany informacji o uwierzytelnianiu między Identity Providerem (IdP) a Service Providerem (SP).
Jak zazwyczaj wygląda ten proces?
-
Użytkownik próbuje uzyskać dostęp do usługi (SP).
-
Usługa przekierowuje go do Identity Providera — w naszym przypadku do portalu opartego na Active Directory.
-
Użytkownik wprowadza login i hasło po stronie IdP.
-
IdP weryfikuje dane i przesyła do usługi asercję SAML (SAML assertion) — dokument XML potwierdzający tożsamość użytkownika.
-
Usługa ufa IdP i przyznaje użytkownikowi dostęp.
Kluczowa zasada: uwierzytelnianie odbywa się po stronie IdP. Usługa nie przechowuje hasła użytkownika — ufa asercji wystawionej przez IdP.
I właśnie w tym tkwił problem, którego biznes nie dostrzegł.
Nasza implementacja: pakiet i konfiguracja
Przeanalizowaliśmy dostępne pakiety, aby nie tworzyć całej integracji od zera. Wybraliśmy aacotroneo/laravel-saml2.
Dlaczego ten pakiet?
-
Udostępnia niezbędne endpointy, w tym metadata, ACS i SLS.
-
Umożliwia konfigurację wymiany danych za pomocą konfiguracji XML.
-
Pozwala zintegrować SAML z naszą logiką i obsługą różnych scenariuszy uwierzytelniania.
Ważne ograniczenie: użytkownicy zewnętrzni nie potrzebowali SAML. Jego celem było zapewnienie jednolitego logowania wyłącznie pracownikom wewnętrznym. Dlatego wdrożyliśmy logikę warunkową: jeśli użytkownik był pracownikiem wewnętrznym, system przekierowywał go do portalu. Użytkownicy zewnętrzni nadal korzystali ze standardowego procesu uwierzytelniania.
Zespół odpowiedzialny za stronę Active Directory dostosował format wymiany danych XML do naszych wymagań. Uruchomiliśmy rozwiązanie.
Jak to działało: szczegóły techniczne
Prześledźmy pełny proces logowania pracownika wewnętrznego.
Krok 1. Wstępna identyfikacja w naszym systemie
Użytkownik otwierał stronę logowania naszego systemu uwierzytelniania i wprowadzał adres e-mail i hasło lub numer telefonu. Był to pierwszy etap procesu uwierzytelniania.
Dlaczego było to konieczne? Musieliśmy ustalić, czy użytkownik powinien logować się przez SAML. Jeśli był pracownikiem wewnętrznym, system rozpoznawał go i przekierowywał do portalu.
Krok 2. Przekierowanie do portalu z danymi w formacie XML
Następnie przekierowywaliśmy użytkownika do portalu, przesyłając dane użytkownika w postaci dokumentu XML. Portal odbierał dane i wyświetlał własny formularz logowania.
Krok 3. Wprowadzenie danych logowania do portalu
Użytkownik wpisywał login (nie adres e-mail) i hasło do portalu. Był to drugi etap uwierzytelniania.
Krok 4. Odpowiedź SAML i zakończenie logowania
Portal (IdP) weryfikował dane logowania i przesyłał asercję SAML z powrotem do naszego systemu. Walidowaliśmy asercję i kończyliśmy proces logowania.
Sesja pozostawała aktywna przez cały dzień pracy pracownika.
Z technicznego punktu widzenia wszystko było skonfigurowane poprawnie. SAML działał. Jednak z perspektywy doświadczeń użytkownika była to porażka.
Problem: dwa procesy logowania zamiast jednego
Tydzień po uruchomieniu rozwiązania zaczęły napływać skargi. Większość pracowników wewnętrznych zgłaszała, że zamiast ułatwić im pracę, jeszcze bardziej ją skomplikowaliśmy.
Jak wyglądało to w praktyce?
Aby uzyskać dostęp do dowolnej usługi, pracownik musiał:
-
Zalogować się do naszego systemu uwierzytelniania za pomocą adresu e-mail i hasła lub numeru telefonu.
-
Wprowadzić login i hasło do portalu.
Dwa oddzielne procesy logowania. Dwa różne zestawy danych uwierzytelniających.
Biznes zakładał, że dzięki SAML logowanie będzie odbywać się w jednym miejscu, a użytkownik będzie musiał wprowadzić dane tylko raz. Tak się jednak nie stało.
Dlaczego tak się stało: ograniczenie, którego nie usłyszano
Nasz zespół i architekt przed rozpoczęciem prac poinformowali biznes o tym ograniczeniu.
Na czym ono polegało?
W przypadku SAML uwierzytelnianie odbywa się po stronie Identity Providera — w naszym przypadku portalu. Jednak zanim użytkownik dotarł do portalu, nasz system musiał go w jakiś sposób zidentyfikować, aby ustalić, czy jest pracownikiem wewnętrznym i powinien zostać przekierowany do IdP.
Powodowało to powstanie dwóch punktów wejścia:
-
naszego systemu, w którym odbywała się wstępna identyfikacja użytkownika;
-
portalu, w którym następowało właściwe uwierzytelnianie za pośrednictwem SAML.
Ostrzegaliśmy, że użytkownicy będą musieli przejść przez dwa oddzielne procesy logowania. Jednak biznes nie przyjął tego do wiadomości.
Nie był to błąd techniczny. Było to nieporozumienie między biznesem a rzeczywistością techniczną. Biznes chciał mieć jeden punkt wejścia, ale w tej konkretnej architekturze SAML nie zapewniał takiego rozwiązania.
Rezultat: półtora miesiąca pracy i wyłączenie rozwiązania
Poświęciliśmy półtora miesiąca na rozwój rozwiązania, które ostatecznie musieliśmy wyłączyć i całkowicie porzucić.
Co nam to dało?
-
Praktyczne doświadczenie z SAML 2.0 i pakietem
aacotroneo/laravel-saml2. -
Lepsze zrozumienie ograniczeń protokołu w kontekście doświadczeń użytkownika.
-
Lekcję dotyczącą tego, jak ważne jest wyjaśnianie ograniczeń technicznych biznesowi w zrozumiały dla niego sposób.
Jakie były koszty?
-
Półtora miesiąca pracy zespołu.
-
Niezadowolenie pracowników i tydzień skarg.
-
Konieczność wycofania rozwiązania. Na szczęście elastyczna konfiguracja, którą wdrożyliśmy, pozwoliła nam szybko przywrócić poprzedni sposób logowania.
Czego nauczyliśmy się z tego doświadczenia?
1. SAML to nie „logowanie jednym kliknięciem”
SAML rozwiązuje problem uwierzytelniania federacyjnego, ale nie eliminuje potrzeby wstępnej identyfikacji, jeśli usługa musi ustalić, dokąd przekierować użytkownika.
Jeśli biznes chce mieć jeden punkt wejścia, należy:
-
uczynić portal jedynym punktem wejścia, tak aby użytkownicy przechodzili bezpośrednio do niego;
-
albo zaakceptować dwa etapy logowania jako konsekwencję wybranej architektury.
2. Ograniczenia techniczne trzeba wyjaśniać językiem biznesu
Ostrzegaliśmy biznes, ale najwyraźniej nie przedstawiliśmy problemu wystarczająco obrazowo.
Wniosek: wyjaśniając ograniczenia techniczne, należy pokazywać rzeczywisty scenariusz użytkownika, a nie tylko diagram techniczny.
„Użytkownik będzie musiał dwukrotnie wprowadzić hasło” jest znacznie bardziej zrozumiałe niż „SAML wymaga wstępnej identyfikacji po stronie SP”.
3. Jeśli nas nie zrozumiano, odpowiedzialność spoczywa również na zespole
Jeśli biznes nie zrozumiał konsekwencji, oznacza to, że nie udało nam się wystarczająco skutecznie ich wyjaśnić.
To nieprzyjemny, ale ważny wniosek: racja techniczna nie chroni projektu przed porażką, jeśli klient nie rozumie konsekwencji podejmowanych decyzji.
4. Nieudane wdrożenie również jest cennym doświadczeniem
Zdobyliśmy praktyczną wiedzę, którą niełatwo uzyskać: nauczyliśmy się konfigurować SAML z Active Directory, pracować z aacotroneo/laravel-saml2 i rozumieć wymianę danych w formacie XML.
Przy kolejnym projekcie integracji z SAML będziemy wiedzieć nie tylko, jak ją wdrożyć, lecz także jakich pułapek unikać.
Szczegóły techniczne SAML, które warto znać
Jeśli planujesz podobną integrację, warto poznać kilka podstawowych pojęć.
Identity Provider (IdP) — strona odpowiedzialna za uwierzytelnianie użytkownika. W naszym przypadku był to portal oparty na Active Directory.
Service Provider (SP) — strona, która ufa wynikowi uwierzytelniania dostarczonemu przez IdP. W naszym przypadku był to nasz system uwierzytelniania.
SAML Assertion — dokument XML wystawiany przez IdP i przesyłany do SP. Zawiera potwierdzenie tożsamości użytkownika oraz może zawierać atrybuty, takie jak adres e-mail czy role.
ACS (Assertion Consumer Service) — endpoint po stronie SP, na który IdP przesyła asercję SAML. W pakiecie aacotroneo/laravel-saml2 ta trasa jest tworzona automatycznie.
Metadata — dokument XML zawierający konfigurację SP lub IdP, w tym adresy URL, certyfikaty i inne parametry niezbędne do wymiany danych. W tym pakiecie metadane są dostępne pod adresem /{idpName}/metadata.
Wyzwania związane z wdrożeniem SAML:
-
Skomplikowana konfiguracja obejmująca XML, metadane i certyfikaty.
-
Trudne debugowanie — błędy związane z podpisami XML nie zawsze są oczywiste.
-
Ograniczona elastyczność w projektowaniu niektórych scenariuszy uwierzytelniania użytkowników.
Podsumowanie
Ta historia pokazuje, że rozwiązanie poprawne technicznie może okazać się porażką z perspektywy użytkownika.
SAML działał. Jednak zamiast uprościć pracę, zmusiliśmy pracowników do dwukrotnego logowania — i ich frustracja była uzasadniona.
Ostrzegaliśmy biznes, ale konsekwencje nie zostały właściwie zrozumiane. W rezultacie spędziliśmy półtora miesiąca na opracowaniu rozwiązania, które następnie musieliśmy wyłączyć.
Była to ważna lekcja dla naszego zespołu. Mamy nadzieję, że okaże się przydatna również dla osób rozważających wdrożenie SAML we własnej infrastrukturze.