Uwierzytelnianie za pomocą serwera backendu

Jeśli używasz Logowania przez Google w aplikacji lub witrynie, która komunikuje się z serwerem backendu, może być konieczne zidentyfikowanie aktualnie zalogowanego użytkownika na serwerze. Aby zrobić to w bezpieczny sposób, po zalogowaniu się użytkownika wyślij jego token identyfikatora na swój serwer przy użyciu protokołu HTTPS. Następnie sprawdź na serwerze integralność tokena tożsamości i wykorzystaj zawarte w nim informacje o użytkowniku do zainicjowania sesji lub utworzenia nowego konta.

Wyślij token identyfikatora na swój serwer

Gdy użytkownik się zaloguje, pobierz jego token identyfikatora:

function onSignIn(googleUser) {
  var id_token = googleUser.getAuthResponse().id_token;
  ...
}

Następnie wyślij token identyfikatora na swój serwer za pomocą żądania HTTPS POST:

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://yourbackend.example.com/tokensignin');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
  console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('idtoken=' + id_token);

Sprawdź integralność tokena tożsamości

Po otrzymaniu tokena identyfikatora za pomocą HTTPS POST musisz zweryfikować jego integralność.

To verify that the token is valid, ensure that the following criteria are satisfied:

  • The ID token is properly signed by Google. Use Google's public keys (available in JWK or PEM format) to verify the token's signature. These keys are regularly rotated; examine the Cache-Control header in the response to determine when you should retrieve them again.
  • The value of aud in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server.
  • The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
  • The expiry time (exp) of the ID token has not passed.
  • If you want to restrict access to only members of your G Suite domain, verify that the ID token has an hd claim that matches your G Suite domain name.

Rather than writing your own code to perform these verification steps, we strongly recommend using a Google API client library for your platform, or a general-purpose JWT library. For development and debugging, you can call our tokeninfo validation endpoint.

Korzystanie z biblioteki klienta interfejsów API Google

Użycie jednej z bibliotek klienta interfejsu API Google (np. Java, Node.js, PHP lub Python) to zalecany sposób weryfikacji tokenów identyfikatorów Google w środowisku produkcyjnym.

Java

Aby zweryfikować token identyfikatora w Javie, użyj obiektu GoogleIdTokenVerifier. Na przykład:

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;

...

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
    // Specify the CLIENT_ID of the app that accesses the backend:
    .setAudience(Collections.singletonList(CLIENT_ID))
    // Or, if multiple clients access the backend:
    //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
    .build();

// (Receive idTokenString by HTTPS POST)

GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
  Payload payload = idToken.getPayload();

  // Print user identifier
  String userId = payload.getSubject();
  System.out.println("User ID: " + userId);

  // Get profile information from payload
  String email = payload.getEmail();
  boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
  String name = (String) payload.get("name");
  String pictureUrl = (String) payload.get("picture");
  String locale = (String) payload.get("locale");
  String familyName = (String) payload.get("family_name");
  String givenName = (String) payload.get("given_name");

  // Use or store profile information
  // ...

} else {
  System.out.println("Invalid ID token.");
}

Metoda GoogleIdTokenVerifier.verify() weryfikuje podpis JWT, deklaracje aud, iss i exp.

Jeśli chcesz ograniczyć dostęp tylko do członków Twojej domeny G Suite, zweryfikuj też zgłoszenie hd, sprawdzając nazwę domeny zwracaną przez metodę Payload.getHostedDomain().

Node.js

Aby zweryfikować token identyfikatora w Node.js, użyj biblioteki uwierzytelniania Google dla Node.js. Zainstaluj bibliotekę:

npm install google-auth-library --save
Następnie wywołaj funkcję verifyIdToken(). Na przykład:

const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client();
async function verify() {
  const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
      // Or, if multiple clients access the backend:
      //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
  });
  const payload = ticket.getPayload();
  const userid = payload['sub'];
  // If request specified a G Suite domain:
  // const domain = payload['hd'];
}
verify().catch(console.error);

Funkcja verifyIdToken weryfikuje podpis JWT, aud, exp i iss.

Jeśli chcesz ograniczyć dostęp tylko do członków Twojej domeny G Suite, sprawdź też, czy zgłoszenie hd odpowiada nazwie Twojej domeny G Suite.

PHP

Aby zweryfikować token identyfikatora w języku PHP, użyj biblioteki klienta interfejsu API Google dla języka PHP. Zainstaluj bibliotekę (na przykład za pomocą narzędzia Composer):

composer require google/apiclient
Następnie wywołaj funkcję verifyIdToken(). Na przykład:

require_once 'vendor/autoload.php';

// Get $id_token via HTTPS POST.

$client = new Google_Client(['client_id' => $CLIENT_ID]);  // Specify the CLIENT_ID of the app that accesses the backend
$payload = $client->verifyIdToken($id_token);
if ($payload) {
  $userid = $payload['sub'];
  // If request specified a G Suite domain:
  //$domain = $payload['hd'];
} else {
  // Invalid ID token
}

Funkcja verifyIdToken weryfikuje podpis JWT, aud, exp i iss.

Jeśli chcesz ograniczyć dostęp tylko do członków Twojej domeny G Suite, sprawdź też, czy zgłoszenie hd odpowiada nazwie Twojej domeny G Suite.

Python

Aby zweryfikować token identyfikatora w Pythonie, użyj funkcji verify_oauth2_token. Na przykład:

from google.oauth2 import id_token
from google.auth.transport import requests

# (Receive token by HTTPS POST)
# ...

try:
    # Specify the CLIENT_ID of the app that accesses the backend:
    idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)

    # Or, if multiple clients access the backend server:
    # idinfo = id_token.verify_oauth2_token(token, requests.Request())
    # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]:
    #     raise ValueError('Could not verify audience.')

    # If auth request is from a G Suite domain:
    # if idinfo['hd'] != GSUITE_DOMAIN_NAME:
    #     raise ValueError('Wrong hosted domain.')

    # ID token is valid. Get the user's Google Account ID from the decoded token.
    userid = idinfo['sub']
except ValueError:
    # Invalid token
    pass

Funkcja verify_oauth2_token weryfikuje podpis JWT, deklarację aud i deklarację exp. Musisz też zweryfikować żądanie hd (jeśli dotyczy), sprawdzając obiekt zwracany przez verify_oauth2_token. Jeśli do serwera backendu uzyskuje dostęp wielu klientów, również ręcznie zweryfikuj deklarację aud.

Wywoływanie punktu końcowego tokeninfo

Łatwym sposobem na zweryfikowanie podpisu tokena identyfikatora na potrzeby debugowania jest użycie punktu końcowego tokeninfo. Wywołanie tego punktu końcowego obejmuje dodatkowe żądanie sieciowe, które wykonuje większość weryfikacji za Ciebie, a jednocześnie testujesz prawidłową weryfikację i wyodrębnianie ładunków we własnym kodzie. Nie można go stosować w kodzie produkcyjnym, ponieważ żądania mogą być ograniczane lub w inny sposób powodować przejściowe błędy.

Aby zweryfikować token identyfikatora za pomocą punktu końcowego tokeninfo, wyślij żądanie HTTPS POST lub GET do punktu końcowego i przekaż token identyfikatora w parametrze id_token. Aby na przykład zweryfikować token „XYZ123”, wyślij następujące żądanie GET:

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

Jeśli token jest prawidłowo podpisany, a żądania iss i exp mają oczekiwane wartości, otrzymasz odpowiedź HTTP 200, w której treść zawiera żądania tokena identyfikatora w formacie JSON. Przykładowa odpowiedź:

{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

Jeśli jesteś klientem G Suite, może zainteresować Cię twierdzenie hd, które wskazuje hostowaną domenę użytkownika. Można go używać, aby ograniczyć dostęp do zasobu tylko do użytkowników z określonych domen. Brak tego stwierdzenia oznacza, że użytkownik nie należy do domeny hostowanej przez G Suite.

Tworzenie konta lub sesji

Po zweryfikowaniu tokena sprawdź, czy użytkownik znajduje się już w bazie danych użytkowników. Jeśli tak, ustanowij sesję uwierzytelnioną dla użytkownika. Jeśli użytkownika nie ma jeszcze w bazie danych, utwórz nowy rekord użytkownika na podstawie informacji z ładunku tokena identyfikatora i załóż dla niego sesję. Po wykryciu nowo utworzonego użytkownika w aplikacji możesz poprosić użytkownika o podanie wszelkich dodatkowych informacji profilowych, których potrzebujesz.

Zabezpieczanie kont użytkowników za pomocą ochrony obejmującej wiele kont

Logując użytkowników przez Google, automatycznie korzystasz ze wszystkich funkcji zabezpieczeń i infrastruktury Google, które chronią dane tego użytkownika. Jednak w mało prawdopodobnym przypadku naruszenia bezpieczeństwa konta Google użytkownika lub wystąpienia innego ważnego zdarzenia związanego z bezpieczeństwem aplikacja też może być podatna na atak. Aby lepiej chronić swoje konta przed ważnymi zdarzeniami związanymi z bezpieczeństwem, korzystaj z Ochrony wszystkich kont, dzięki której możesz otrzymywać alerty zabezpieczeń od Google. Gdy otrzymasz takie zdarzenia, uzyskasz wgląd w ważne zmiany dotyczące bezpieczeństwa konta Google użytkownika i możesz podjąć odpowiednie działania w swojej usłudze, aby zabezpieczyć swoje konta.