Jak zrezygnowaliśmy z Vue.js na rzecz niezawodności: historia jednego modułu uwierzytelniania

Powtarzające się problemy z zapętlaniem logowania skłoniły nas do zbadania przyczyn. Okazało się, że starsze urządzenia i przeglądarki w połączeniu z firmowym oprogramowaniem zabezpieczającym generowały ruch przypominający atak DDoS z powodu specyfiki Vue.js. Podjęliśmy decyzję o przeniesieniu usługi uwierzytelniania na najprostszy stos: HTML, CSS i czysty JavaScript, bez bibliotek. Po migracji problem całkowicie zniknął, a logowanie działa stabilnie także na starszych urządzeniach użytkowników.

Jak zrezygnowaliśmy z Vue.js na rzecz niezawodności: historia jednego modułu uwierzytelniania

Kontekst: duży projekt i SSO

Nasz zespół został zaproszony do dużego projektu, w którym odpowiadaliśmy za moduł jednokrotnego logowania (SSO) — wspólny punkt logowania do wszystkich pozostałych usług ekosystemu.

Stos technologiczny projektu:

  • Backend: Laravel
  • Frontend: Vue.js
  • Baza danych: MySQL
  • Kolejki: RabbitMQ
  • Uwierzytelnianie: SAML

Nasza rola wydawała się standardowa: zapewnić użytkownikom płynne logowanie do wszystkich usług za pośrednictwem jednego modułu. Wszystko działało — do pewnego momentu.

Problem: zapętlające się logowanie

Zaczęły regularnie napływać zgłoszenia: podczas próby logowania strony wpadały w pętlę, a użytkownicy nie mogli się zalogować.

Użytkownicy skarżyli się na:

  • Niekończące się przekierowania.
  • Zawieszanie się na ekranie logowania.
  • Brak możliwości ukończenia procesu uwierzytelniania.

Początkowo wyglądało to na odosobniony błąd. Jednak liczba zgłoszeń rosła, ponieważ z serwisu zaczęto korzystać na masową skalę. Zaczęliśmy szczegółowo analizować problem.

Diagnostyka: co zakłócało uwierzytelnianie

Wdrożyliśmy rozszerzone logowanie zdarzeń, zebraliśmy dane z frontendu i backendu oraz przeanalizowaliśmy wzorce ruchu. Odkryliśmy coś nieoczywistego.

Część użytkowników korzystała ze starszych urządzeń i przeglądarek. Samo w sobie nie stanowiło to problemu — wiele usług obsługuje starsze środowiska. Jednak u tych użytkowników zainstalowano firmowe oprogramowanie zabezpieczające ze specyficzną konfiguracją, którego stosowanie było wymagane przez dział bezpieczeństwa firmy.

Mechanizm wyglądał następująco:

  1. Przeglądarka ładowała stronę logowania opartą na Vue.js.
  2. Firmowe oprogramowanie zabezpieczające analizowało ruch i zachowanie strony.
  3. Ze względu na specyfikę działania Vue.js — dynamiczne ładowanie, żądania asynchroniczne i aktualizacje DOM — oprogramowanie błędnie interpretowało tę aktywność.
  4. W odpowiedzi zaczynało blokować żądania lub inicjować je ponownie.
  5. Każde takie żądanie trafiało na serwer, a cały proces powtarzał się wielokrotnie.

W rezultacie setki użytkowników korzystających z takiego oprogramowania nieświadomie generowały ruch odpowiadający atakowi DDoS na nasz serwis uwierzytelniania — nie ze złej woli, lecz wskutek błędnej reakcji oprogramowania ochronnego.

Problemem nie było samo obciążenie. Problem polegał na konflikcie nowoczesnego frontendu JavaScript z firmowymi systemami zabezpieczeń działającymi po stronie klienta.

Rozwiązanie: minimalizm zamiast nowoczesności

Podjęliśmy niepopularną, ale w tej sytuacji jedyną słuszną decyzję: przenieść serwis uwierzytelniania na możliwie najprostszy stos technologiczny.

Wykorzystaliśmy:

  • HTML — statyczną strukturę strony, bez dynamicznego generowania.
  • CSS — zwykłe style, bez frameworków i preprocesorów.
  • Czysty JavaScript — bez bibliotek, frameworków i narzędzi do budowania aplikacji.

Usunęliśmy:

  • Vue.js wraz z całym jego ekosystemem.
  • Asynchroniczne ładowanie komponentów.
  • Routing SPA.
  • Zbędne żądania XHR na etapie uwierzytelniania.

Kluczowa zasada: strona logowania powinna być na tyle prosta, żeby nie „przestraszyła” żadnej przeglądarki ani żadnego systemu zabezpieczeń.

Rezultat: zero incydentów

Po przejściu na prosty stos technologiczny:

  • Nie odnotowaliśmy ani jednego incydentu związanego z działaniem naszego serwisu.
  • Nie występowały konflikty z firmowym oprogramowaniem zabezpieczającym.
  • Zniknęły zapętlenia i niekończące się przekierowania.
  • Obciążenie serwera uwierzytelniania zmniejszyło się kilkukrotnie.

Funkcjonalność przy tym nie ucierpiała: użytkownicy nadal korzystają z jednokrotnego logowania do wszystkich usług ekosystemu.

Wnioski z tej historii

Nowoczesny stos nie zawsze wygrywa

Vue.js, React i inne frameworki świetnie sprawdzają się w produktach, których odbiorcą jest zwykły użytkownik z nowoczesną przeglądarką. Jednak w przypadku krytycznego modułu uwierzytelniania w środowisku korporacyjnym priorytetem nie jest szybkość tworzenia oprogramowania, lecz przewidywalność i kompatybilność.

Użytkownik nie zawsze jest winny

Gdy pojawiają się zgłoszenia dotyczące „starych urządzeń”, łatwo zrzucić winę na użytkownika. Prawdziwa przyczyna często leży jednak głębiej: na styku starszych przeglądarek i nowoczesnego frontendu powstają konflikty niewidoczne w środowisku testowym.

Logowanie zdarzeń to podstawa diagnostyki

Bez szczegółowych logów nigdy nie zauważylibyśmy, że problem nie tkwi w samym obciążeniu, lecz we wzorcu żądań. Logi pokazały, że żądania nie pochodziły od „atakujących”, ale od rzeczywistych użytkowników korzystających z oprogramowania ochronnego.

Czasem krok wstecz oznacza postęp

Rezygnacja z Vue.js na rzecz czystego JavaScriptu wyglądała jak krok wstecz. W rzeczywistości była to decyzja inżynierska podyktowana warunkami eksploatacji, a nie modą.

Na zakończenie

Ta historia nie jest o tym, że Vue.js jest zły. Pokazuje, że decyzje architektoniczne należy podejmować w oparciu o kontekst, a nie trendy.

W module uwierzytelniania dużego ekosystemu korporacyjnego minimalizm okazał się bardziej niezawodny niż nowoczesność. To właśnie taki przypadek, w którym „prościej” oznacza „lepiej”.

Porozmawiajmy o projekcie

Opowiedz o zadaniu — wycenimy w kilka dni

Kontakt