Logowanie w kilku domenach

Wielu webmasterów na pewno spotkało się z problemem, jak zintegrować logowanie do kilku serwisów, znajdujących się pod różnymi domenami. Załóżmy że prowadzę serwisy, które chcę zintegrować:

Gdy użytkownik zaloguje się na www.itlublin.pl, to po przejściu na pozostałe serwisy musi się ponownie logować. Dzieje sie tak dlatgo, że cookie jest ustawione na www.itlublin.pl i tyko do tej domeny przeglądarka je odsyła - dla pozostałych domen muszą być ustawiane nowe ciasteczka.

Przykładowy kod PHP który wysyła takie ciasteczko, potrzebne nam potem do rozpoznawania zalogowanego (lub niezalogowanego) użytkownika, wygląda tak:

setcookie ("user", $cookie_hash, $expire, "/", "www.itlublin.pl");

Jak widać w ostatnim parametrze, ciasteczo zostało ustanowione dla domeny www.itlublin.pl, i tylko spod tej domeny będzie widoczne. Aby było dostępne dla wszystkich subdomen domeny itlublin.pl, należy wprowadzić bardzo prostą zmianę:
setcookie ("user", $cookie_hash, $expire, "/", ".itlublin.pl");

Takie ciasteczko powinno być widoczne dla wszystkich subdomen .itlublin.pl. Kropka na początku wedlug specyfikacji netscape nie jest konieczna, lecz niektóre przeglądarki tego wymagają.

Hash w linku do drugiego serwisu

Co jednak, gdy nasze serwisy znajdują się w zupełnie różnych domenach?

Bardzo prostym sposobem, stosowanym np. przez linux.pl, jest hash weryfikujący przy przechodzeniu do drugiego serwisu. Działa to w następujący sposób:

  1. użytkownik loguje sie na linux.pl
  2. na odesłanej stronie linux.pl w linku do innego serwisu (załóżmy: linuxnewbie.pl) znajduje się hash, nazwijmy go $hash, który jest inny dla każdego zalogowanego użytkownika
  3. użytkownik chce przejść na forum, i klika w link który prowadzi do linuxnewbie.pl?loginhash=$hash
  4. serwer na podstawie $hash wie, że to jest ten sam zalogowany użytkownik, i na linuxnewbie.pl wysyła cookie, po którym rozpoznaje użytkownika w tej domenie

Ma to jednak tą wadę, że gdy wpiszę po prostu w nowym oknie przeglądarki linuxnewbie.pl, to nie jestem zalogowany nadal. Albo wcześniej wszedłem na tą stronę i była cały czas otwarta, lecz po zalogowaniu na drugim serwisie, i odświeżeniu strony, nie będę zalogowany.

Logowanie z przekierowaniem

Technika przekierowania na drugą domenę już przy logowaniu, pozwala uniknąć takich problemów.

Przykładowo, użytkownik loguje się w domenie itlublin.pl. Chcę jednak, by był równocześnie zalogowany w domenie sklep.com. Co się dzieje w czasie logowania:

  1. użytkownik loguje się na itlublin.pl (wysyła login i hasło z formularza)
  2. serwer generuje hash, nazwijmy go $hash
  3. itlublin.pl odsyła do użytkownika stronę, która:
    • ustawia cookie, po którym użytkownik jest teraz rozpoznawany w domenie itlublin.pl
    • przekierowuje na stronę sklep.com?loginhash=$hash
  4. serwer obsługujący domenę sklep.com otrzymuje żądanie z hashem w linku, sprawdza w bazie danych że użytkownik legitymujący się tym hashem został zalogowany na itlublin.pl
    • zaznacza w bazie danych, że ten hash został wykorzystany (kasuje go)
  5. sklep.com wysyła do użytkownika stronę, która ustawia cookie, i po tym ciasteczku będzie on teraz rozpoznawany jako zalogowany użytkownik

Ma to tę zaletę, że dla uzytkownika jest to praktycznie niewidoczny mechanizm (poza nieco dłuższym czasem przy logowaniu się, z powodu przekierowań). Z tego typu mechanizmu korzysta np. google.

Opisany trick sprawdza się doskonale, jeżli posiadamy tylko 2 domeny - co jednak, gdy mamy ich np. 10? Wtedy te przekierowania potrafią znacznie opóźnić proces logowania. Przyjrzyjmy się serwisowi google (nie wiem czy taki mechanizm stosują, ale w tym przypadku byłby bardzo praktyczny). Google posiada domeny w różnych językach:

  • google.com - domena główna
  • google.pl
  • google.es
  • ... itd

Mam konto użytkownika skonfigurowane na język polski. Loguję się do google.pl - wtedy wyżej opisany mechanizm loguje mnie na google.pl i google.com. Podobnie gdy loguję się z google.com, serwis wykrywa moje ustawienia językowe, i loguje mnie automatycznie do google.pl.

Ale zachciało mi się wejść jeszcze na google.es. Tutaj nie jestem już zalogowany, ale nie muszę ponownie wpisywać loginu i hasła:

  1. klikam w link "Zaloguj"
  2. serwer wykrywa, że spod tego IP zalogowany jest na innym serwisie google użytkownik (można dodatkowo sprawdzać po tym jak przedstawia się przeglądarka)
  3. odsyła stronę przekierowującą mnie na google.com?checklogin&hash=$hash (tutaj znów używamy jednorazowego hasha, dla weryfikacji), i zapamiętuje że wysłał przekierowanie z tym hashem
  4. google.com odbiera żądanie z hashem, oraz przypisane dla domeny google.com cookie, i potwierdza w bazie danych, że jest to ten sam użytkownik; następnie wysyła przekierowanie z powrotem na google.es
  5. google.es powiązuje cookie z zalogowanym użytkownikiem (zwróć uwagę, że można wcześniej ustawić ciasteczko jako niezalogowanemu użytkownikowi, a dopiero potem nadać mu uprawnienia użytkownika zalogowanego)

Jeżeli jednak nie jest to ten zalogowany użytkownik (np. korzysta z innej przeglądarki, lub kilka komputerów podłączonych przez proxy), to wtedy w punkcie 5. serwer wysyła do nas formularz logowania.

A dlaczego nie zastosować "sprytniejszego" mechanizmu? Od razu jak wchodzę na google.es, serwer zauważa że pod tym IP jest zalogowany gdzie indziej użytkownik, i od razu przekierowuje w celu sprawdzenia. Tylko że taki "sprytniejszy" sposób będzie bardzo uciążliwy dla użytkowników korzystających z proxy...

Tyle na dziś o mechanizmach autoryzacji. Wszelkie algorytmy są wymyślone przeze mnie, nie znam szczegółów działania podanych jako przykłady witryn internetowych i nawet nie analizowałem ich działania.

Kopiowanie niniejszego artykułu jest dozwolone w celach komercyjnych i niekomercyjnych, pod warunkiem że zamieścisz informację iż pochodzi on ze strony www.itlublin.pl