Web Design Blog / Programowanie:

Integracja logowania Google Sign-In w PHP

Dawno nie było tutorialu dla programistów PHP / JavaScript. W tym wpisie przebrniemy przez proces integracji Front-Endu i Back-Endu z Google API na przykładzie usługi Google Sign-In, czyli niesamowicie użytecznej i ułatwiającej życie funkcji „Zaloguj przez Google„Czyli logowania z wykorzystaniem zaufanej strony trzeciej (federated login).

Jakie są korzyści z posiadania funkcji „Zaloguj przez Google”?

Przeciętny użytkownik Internetu korzysta obecnie z coraz większej ilości aplikacji i usług internetowych, które wymagają logowania. To powoduje, że ustalane hasła są trudne zapamiętania lub co gorsza, użytkownicy ustalają kilka haseł, które są wykorzystywane na wielu różnych serwisach co jest ryzykowne z punktu widzenia bezpieczeństwa.

Kolejnym problemem jest User Experience. Jak wiadomo konieczność wprowadzania od nowa w każdej kolejnej aplikacji ciągle tych samych danych tj. imię, nazwisko, adres e-mail, data urodzenia przyprawia o co najmniej ból głowy lub w skrajnych przypadkach rezygnujemy z wypełniania formularza złożonego z kilkunastu pól.

Rozwiązaniem na takie problemy jest między innymi „Federated login” czyli uwierzytelnianie i uzupełnienie profilu użytkownika z wykorzystaniem tożsamości przechowywanej na koncie w zaufanym serwisie zewnętrznym. Jak widać, Federated login rozwiązuje problem zarówno użytkowników jak i deweloperów.

Zasada działania Google Sign-In

Jednym z możliwych sposobów integracji Google Sign-In we własnej aplikacji jest umieszczenie Biblioteki Platformy Google (Google Platform Library) i wygenerowanie za jego pomocą po stronie klienta przycisku, który prześle do back-endu niezbędne informacje do uwierzytelnienia użytkownika:

Przycisk Google Sign-In

Poprawna implementacja polega na wykorzystaniu otrzymywanego przy każdym logowaniu unikalnego ID_Token, który jest przesyłany do back-endu za pomocą bezpiecznego połączenia SSL.

Proces logowania za pomocą Google Sign-In

Otrzymany ID_Token jest rozszyfrowany za pomocą biblioteki Google, która trzeba zainstalować na serwerze. W aplikacji identyfikujemy użytkownika za pomocą pola „subject”, które jest unikalne dla każdego wiązania użytkownik – aplikacja.

Krok 1: Utworzenie nowego projektu w Konsoli „Google for Developers”

Wypełniamy wszystkie pola według etykiet. Nie zapomnijmy dodać jakieś polityki prywatności bo Google nie pozwoli nam na logowanie się użytkowników.

Nowy projekt w Konsoli dla deweloperów

 

Krok 2: Stworzenie identyfikatora OAuth

Następnym krokiem jest stworzenie identyfikatora OAuth. Do celów bezpieczeństwa należy określić źródło kodu JavaScript oraz podać URI do przekierowania.

Tworzenie identyfikatora i klucz OAuth

 

Po poprawnym uzupełnieniu formularza otrzymujemy identyfikator klienta, który jest wykorzystywany do komunikacji z Google API.

Identyfikator i klucz tajny OAuth

Krok 3: Integracja po stronie Front-Endu (HTML, JavaScript)

Integracja po stronie klienta polega na dodaniu kodu znacznika meta „google-signin-client_id” z otrzymanym identyfikatorem klienta OAuth oraz dodaniu wcześniej wspomnianej biblioteki Google Platform.

W sekcji head dodajemy:

<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id" content="*** ID otrzymany w poprzednim kroku ***.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer>
{lang:'pl'}
</script>

Linijka lang: ‚pl’ jak można się domyślić podmienia napis na przycisku z „Sign-In” na „Zaloguj się”.

A w miejscu gdzie chcemy wyświetlić przycisk:

<div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>

Teraz jeszcze pozostaje nam pobrać id_token i przesłać go do back-endu. Dla wygody skorzystamy z metody post w jQuery:

<script>
  function onSignIn(googleUser) {
    // Przykładowe dane które możemy pobrać we frontendzie
    var profile = googleUser.getBasicProfile();
    console.log("ID: " + profile.getId()); // Pod żadnym pozorem nie wysyłany tego do back-endu!
    console.log('Nazwa: ' + profile.getName());
    console.log('Imię: ' + profile.getGivenName());
    console.log('Nazwisko: ' + profile.getFamilyName());
    console.log("Adres URL do zdjęcia profilowego: " + profile.getImageUrl());
    console.log("E-mail: " + profile.getEmail());
  
    // To w tym miejscu pobieramy id_token:
    var id_token = googleUser.getAuthResponse().id_token;
    console.log("ID Token: " + id_token);
    $.post("https://w3tech.pl/public/user/googlelogin", {token: id_token}, function(output){   
    //ścieżka do metody PHP obsługującej przesyłany id_token

    var data = $.parseJSON(output);

    if (data['status'] == "1"){
      window.location.href="https://[ścieżka docelowa po zalogowaniu]";
    }
    if (data['status'] == "2"){
      location.reload(); //Nieudane logowanie? Jeszcze raz...
    }
  });
  };
</script>

Dzięki temu możemy wywołać okno, przez które logują użytkownicy:

Okno logowania

 

Kod HTML i JavaScript na stronie do logowania / rejestracji

Na tym etapie decydujemy jakich uprawnień będziemy wymagać od użytkownika. Dla celów projektu  wystarczą nam podstawowe informacje o profilu oraz e-mail, co deklarujemy również w w znaczniku meta „google-sign-in-scope”. Użytkownik udziela je nam w następnym kroku jest to spełnienie zasady „incremental authorization” polegającej na tym aby aplikacja żądała konkretnych uprawnień wtedy kiedy to konieczne.

Tworzymy obiekt profilu za pomocą googleUser.getBasicProfile(); następnie pobieramy token za pomocą googleUser.getAuthResponse().id_token; Otrzymany token wysyłamy za pomocą jQuery.post.

Token przechowuje dane o użytkowniku w sposób niejawny co uniemożliwia podmianę danych po stronie klienta, przykładowy id_token wygląda mniej więcej tak:

OAuth id_token przykład

Krok 4: Integracja po stronie Back-Endu

!!! Ważna uwaga !!! Nie można identyfikować użytkowników za pomocą pola ID lub e-mail, do których mamy dostęp po zalogowaniu z poziomu klienta, ponieważ taki sposób identyfikacji były podatny na podmienianie przesyłanych do back-endu danych.

Aby zweryfikować integralność id_token musimy zainstalować na serwerze Google API Client Library za pomocą Composera.

Zainstaluj Bibliotekę Google API z poziomu composera:

composer require google/apiclient

Teraz przechodzimy do logiki naszej istniejącej aplikacji. Na początku warto byłoby dołączyć bibliotekę:

require_once '../../../vendor/autoload.php';

Pobieramy id_token z Front-Endu:

$id_token = $_POST["token"];

W miejscu gdzie jest nam to potrzebne, korzystamy z wbudowanej w bibliotece metod:

$client_id = '** ID otrzymany w poprzednim kroku **.apps.googleusercontent.com';

$client = new Google_Client(['client_id' => $client_id]);
$payload = $client->verifyIdToken($id_token);
if ($payload) {

$sub = $payload['sub'];
$aud = $payload['aud'];
$email = $payload['email'];
$nazwa = $payload['name'];

} else {
// Tutaj można zwrócić błąd braku weryfikacji i przerwać akcję (błąd w kodzie, kluczach lub atak)
}

Przesłany do back-endu token umożliwia otrzymanie niepublicznego pola „sub” dzieje się to za pomocą opisanych w dokumentacji metod verifyIdToken($id_token). Wartość „subject” będzie służyła nam do jednoznacznej identyfikacji użytkownika.

To tyle! W zmiennej $sub mamy unikalny klucz klienta, który na upartego można spokojnie przechowywać w bazie danych w jawnej postaci.

Krok 5: Dostosowanie back-endu istniejącej aplikacji

Reszta pracy będzie polegała na dostosowaniu wewnętrznych metod do współpracy z nową metodą logowania. Bazując na opisywanym już własnym Frameworku MVC dla PHP  po prostu dodałem dodatkową metodę w kontrolerze user.php:

public function googlelogin(){
$user = $this -> model(„Uzytkownicy”);
$user -> zalogujUzytkownikaGoogle($_POST[„token”]);

echo $output;
}

w modelu Uzytkownicy.php, metoda public function zalogujUzytkownikaGoogle($token = „”);

Ustawia sesję zalogowania lub zwraca ewentualny błąd.

Pole „sub” jest przechowywane może być przechowywane np. w polu „passsword” taki zabieg zwalnia z konieczności modyfikacji bazy danych. Przy każdym logowaniu aplikacja sprawdza czy konkretny użytkownik istnieje. Jeżeli nie, rejestruje nowego użytkownika, a jeżeli tak – loguje.

Podsumowanie

Jak widać integracja aplikacji internetowej z usługą Google Sign-In jest banalnie prosta. Pamiętaj aby do uwierzytelniania używać pola subject, które jest bezpiecznie wyciągane w back-endzie aplikacji.

Źródła

https://developers.google.com/identity/sign-in/web/sign-in

https://developers.google.com/identity/sign-in/web/backend-auth

 

Integracja logowania Google Sign-In w PHP
4.7 (93.33%) głosów: 15

Autor: (29 lat)

Służę pomocą w razie wykonania / odnowienia strony lub sklepu internetowego dla twojej firmy niezależnie od twojej lokalizacji czy skali przedsięwziecia.

Tego typu wpisy piszę w wolnych chwilach lub pomiędzy projektami. Tylko pomyśl co mogę dla Ciebie zrobić w ramach usługi :-)

Zadaj pytanie lub skomentuj

Wyrażam zgodę na przetwarzanie moich danych osobowych przez firmę Paweł Mansfeld z siedzibą w Jastrzębiu-Zdroju, ul. Plebiscytowa 10, w celu udzielenia odpowiedzi, w tym przedłożenia oferty jeśli o nią pytam. Moje dane osobowe będą przetwarzane do czasu cofnięcia zgody lub przez okres niezbędny do ustalenia, dochodzenia lub obrony roszczeń. Mam prawo dostępu do danych, sprostowania, usunięcia lub ograniczenia przetwarzania, prawo sprzeciwu, prawo wniesienia skargi do organu nadzorczego i prawo do przeniesienia danych.

Komentarze publiczne

Brak komentarzy.
Otrzymuj powiadomienie o nowych artykułach

Wyrażam zgodę na przetwarzanie moich danych osobowych przez firmę Paweł Mansfeld z siedzibą w Jastrzębiu-Zdroju, ul. Plebiscytowa 10, w celu udzielenia odpowiedzi, w tym przedłożenia oferty jeśli o nią pytam. Moje dane osobowe będą przetwarzane do czasu cofnięcia zgody lub przez okres niezbędny do ustalenia, dochodzenia lub obrony roszczeń. Mam prawo dostępu do danych, sprostowania, usunięcia lub ograniczenia przetwarzania, prawo sprzeciwu, prawo wniesienia skargi do organu nadzorczego i prawo do przeniesienia danych.

*Bez obaw, nie udostępniam nikomu twojego adresu e-mail