Mozilla Persona: nowy sposób logowania

Mozilla Persona to ujednolicony sposób logowania, oparty o BrowserID, który eliminuje używanie haseł, skraca rejestrację do dwóch kliknięć oraz jest łatwy w implementacji, bo jak zapewniają twórcy wystarczy na to jedno popołudnie. Nie będę się tutaj rozpisywał nad samą ideą projektu, bo o tym już napisano wiele, ale zajmę się przybliżeniem sposobu jego implementacji.

Biblioteka JavaScript

Spróbujmy obalić mit szybkiej implementacji Persony. Na samym początku naszej pracy musimy załadować specjalnie przygotowaną bibliotekę JavaScript, która da nam dostęp do obiektu navigator.id.

<script src="https://login.persona.org/include.js"></script>

Ten niepozorny obiekt udostępnia kilka ważnych metod, które posłużą nam w dalszej części, a są to request(), logout() i watch().

Wywoływanie akcji

Po załadowaniu biblioteki warto by było zaopatrzyć nasz serwis w przycisk do zalogowania i wylogowania. Jako że tworzenie buttonów w HTML to „trudna” sprawa, pominę ten etap, zaznaczając tylko że użyłem „mało znaczących” identyfikatorów signin i signout. Jeżeli chodzi o wygląd, to Mozilla przygotowała kilka buttonów, które spokojnie możemy pożyczyć do siebie. Warto jasno zakomunikować użytkownikowi przy pomocy czego będzie się logował.

Zajmijmy się teraz obsługą akcji logowania:

var signin = document.getElementById('signin');
signin.addEventListener('click', function () {
    navigator.id.request();
}, false);

Nic nadzwyczajnego. Po kliknięciu buttonu zaloguj wywołujemy metodę request(), która otworzy nam okno logowania do Persony. Teraz czas na akcję wylogowywania:

var signout = document.getElementById('signout');
signout.addEventListener('click', function () {
    navigator.id.logout();
}, false);

Jak widać jest jeszcze mniej rzeczy do tłumaczenia. Po kliknięciu w wyloguj wystarczy wywołać metodę logout().

Hmm … jak na razie idzie nam całkiem nieźle, a przecież mieliśmy obalić mit. Przejdźmy więc do czegoś trudniejszego.

Obserwowanie akcji

No dobra, udało nam się wywołać okno logowania i poprawnie zalogować do Persony. Potrafimy nawet wylogować naszego użytkownika! No dobra, ale jak niby serwis ma wiedzieć, że nastąpiło zalogowanie i do tego jeszcze poprawne? Z pomocą przychodzi nam metoda watch(). Najpierw przykład użycia:

navigator.id.watch({
   loggedInUser: null,
   onlogin: function (assertion) {},
   onlogout: function () {}
});

Metoda ta jako parametr przyjmuje obiekt którego składowe opisałem poniżej.

loggedInUser zawiera adres email zalogowanego użytkownika lub null jeżeli jeszcze się nie zalogował. Persona porówna przekazany e-mail z tym, który został użyty przy logowaniu i jeżeli nie będą się one zgadzać to nastąpi wylogowanie.

Metoda onlogin jest wywołana w momencie zalogowania użytkownika. Jak zauważyłeś przekazywany jest do niej parametr assertion. Jest to identyfikator tożsamości, który należy zweryfikować po stronie serwera. Można tutaj użyć ajaxa jak w poniższym przykładzie, który pochodzi z oficjalnej dokumentacji:

$.ajax({
   type: 'POST',
   url: '/auth/login', // This is a URL on your website.
   data: {assertion: assertion},
   success: function(res, status, xhr) {
      window.location.reload(); 
   },
   error: function(res, status, xhr) {
      alert("login failure" + res);
   }
});

Metoda onlogout jest wywoływana w momencie wylogowywania użytkownika. Tutaj również powinniśmy poinformować naszą aplikację o tym fakcie oraz przypisać do loggedInUser wartość null. Posłużę się tutaj znowu przykładem z dokumentacji:

$.ajax({
   type: 'POST',
   url: '/auth/logout', // This is a URL on your website.
   success: function(res, status, xhr) {
      window.location.reload();
   },
   error: function(res, status, xhr) {
      alert("logout failure" + res);
   }
});

Jest jeszcze jedna ważna rzecz. Metody onlogin i onlogout muszą być zaimplementowane w naszej aplikacji, inaczej wywołanie navigatgor.id.watch() zakończy się błędem.

Weryfikacja usera

Czas na ostatni etap implementacji Persony. Jak się pewnie domyślasz nie mamy tutaj żadnych haseł tylko tzw identyfikator tożsamości, który jest przekazywany do metody onlogin. Aby zweryfikować ten identyfikator należy odwołać się do adresu https://verifier.login.persona.org/verify przekazując mu dwa parametry:

  1. assertion – który jest naszym identyfikatorem tożsamości
  2. audience – adres naszej strony, jako serwis do którego użytkownik się loguje.

Jeżeli powyższe dane zostaną zweryfikowane poprawnie powinniśmy otrzymać w odpowiedzi JSON podobny do poniższego:

{
  "status": "okay",
  "email": "bob@eyedee.me",
  "audience": "https://example.com:443",
  "expires": 1308859352261,
  "issuer": "eyedee.me"
}

Dalej to już robota beckendu o którym ja nie będę się rozpisywał. Przykładowe kody w Phytonie i ASP.Net można znaleźć w dokumentacji.

Podsumowanie

To by było na tyle. Jak widać nie udało mi się obalić dzisiejszego mitu, i implementacja faktycznie okazała się bardzo prosta. Czy sam projekt się przyjmie? Czas pokaże.