Uwierzytelniaj w backendzie przy użyciu tokenów identyfikatorów

Klient logowania jednym dotknięciem pobiera token identyfikatora Google, gdy użytkownik wybiera konto Google. Token tożsamości to podpisane potwierdzenie tożsamości użytkownika, które zawiera również podstawowe informacje z jego profilu, prawdopodobnie zawierające adres e-mail zweryfikowany przez Google.

Gdy tokeny tożsamości są dostępne, możesz ich używać do bezpiecznego uwierzytelniania w backendzie aplikacji lub do automatycznego zarejestrowania użytkownika na nowym koncie bez konieczności weryfikowania adresu e-mail użytkownika.

Aby zalogować lub zarejestrować użytkownika przy użyciu tokena identyfikatora, wyślij ten token do backendu aplikacji. W backendzie zweryfikuj token za pomocą biblioteki klienta interfejsu API Google lub biblioteki JWT ogólnego przeznaczenia. Jeśli użytkownik nie logował się wcześniej w aplikacji za pomocą tego konta Google, utwórz nowe konto.

Jeśli opcjonalnie chcesz używać liczby jednorazowej, by uniknąć ataków typu „replay”, użyj polecenia getNonce, by wysłać ją wraz z tokenem identyfikatora do serwera backendu i sprawdzić oczekiwaną wartość. Zalecamy użycie liczb jednorazowych, aby zwiększyć bezpieczeństwo użytkowników.

Pobierz token identyfikatora z obiektu danych logowania

Po pobraniu danych logowania użytkownika sprawdź, czy obiekt danych logowania zawiera token identyfikatora. Jeśli tak, prześlij go do backendu.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
            }
        }
    }
    // ...
}

Sprawdzanie integralności tokena tożsamości

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

Aby sprawdzić, czy token jest prawidłowy, sprawdź, czy są spełnione te kryteria:

  • Token tożsamości jest prawidłowo podpisany przez Google. Do weryfikacji podpisu tokena użyj kluczy publicznych Google (dostępnych w formacie JWK lub PEM). Te klucze są regularnie poddawane rotacji. Sprawdź nagłówek Cache-Control w odpowiedzi, aby określić, kiedy należy je ponownie pobrać.
  • Wartość aud w tokenie identyfikatora jest równa jednemu z identyfikatorów klienta Twojej aplikacji. Ta weryfikacja jest konieczna, by zapobiec używaniu tokenów tożsamości wydanych do szkodliwej aplikacji do uzyskiwania dostępu do danych o tym samym użytkowniku na serwerze backendu aplikacji.
  • Wartość iss w tokenie identyfikatora jest równa accounts.google.com lub https://accounts.google.com.
  • Data ważności (exp) tokena identyfikatora jeszcze nie upłynął.
  • Aby sprawdzić, czy token identyfikatora reprezentuje konto organizacji w Google Workspace lub Cloud, możesz zapoznać się z deklaracją hd, która wskazuje hostowaną domenę użytkownika. Tej opcji należy używać, gdy ograniczasz dostęp do zasobu tylko do użytkowników z określonych domen. Brak takiego roszczenia oznacza, że konto nie należy do domeny hostowanej przez Google.

Zamiast pisać własny kod do wykonywania tych czynności weryfikacyjnych, zdecydowanie zalecamy użycie na platformie biblioteki klienta interfejsu API Google lub ogólnej biblioteki JWT. Na potrzeby programowania i debugowania możesz wywołać nasz punkt końcowy weryfikacji tokeninfo.

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 sprawdzić, czy token identyfikatora reprezentuje konto organizacji w Google Workspace lub Cloud, możesz zweryfikować zgłoszenie hd, sprawdzając nazwę domeny zwracaną przez metodę Payload.getHostedDomain(). Domena w zgłoszeniu email nie jest wystarczająca, aby upewnić się, że konto jest zarządzane przez domenę lub organizację.

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 the request specified a Google Workspace domain:
  // const domain = payload['hd'];
}
verify().catch(console.error);

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

Aby sprawdzić, czy token identyfikatora reprezentuje konto organizacji w Google Workspace lub Cloud, możesz zapoznać się z deklaracją hd, która wskazuje hostowaną domenę użytkownika. Tej opcji należy używać, gdy ograniczasz dostęp do zasobu tylko do użytkowników z określonych domen. Brak takiego roszczenia oznacza, że konto nie należy do domeny hostowanej przez Google.

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 the request specified a Google Workspace domain
  //$domain = $payload['hd'];
} else {
  // Invalid ID token
}

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

Aby sprawdzić, czy token identyfikatora reprezentuje konto organizacji w Google Workspace lub Cloud, możesz zapoznać się z deklaracją hd, która wskazuje hostowaną domenę użytkownika. Tej opcji należy używać, gdy ograniczasz dostęp do zasobu tylko do użytkowników z określonych domen. Brak takiego roszczenia oznacza, że konto nie należy do domeny hostowanej przez Google.

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 the request specified a Google Workspace domain
    # if idinfo['hd'] != DOMAIN_NAME:
    #     raise ValueError('Wrong domain name.')

    # 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"
}

Aby sprawdzić, czy token identyfikatora reprezentuje konto Google Workspace, możesz zapoznać się z deklaracją hd, która wskazuje domenę hostowaną użytkownika. Tej opcji należy używać na potrzeby ograniczania dostępu do zasobu tylko osobom z określonych domen. Brak takiego stwierdzenia oznacza, że konto nie należy do domeny hostowanej w Google Workspace.

Tworzenie konta lub sesji

Po zweryfikowaniu tokena sprawdź, czy użytkownik znajduje się już w bazie danych użytkowników. Jeśli tak, utwórz dla użytkownika uwierzytelnioną sesję. Jeżeli użytkownika nie ma jeszcze w bazie danych, utwórz nowy rekord użytkownika na podstawie informacji w ładunku tokena identyfikatora i zainicjuj sesję dla użytkownika. Gdy wykryjesz w aplikacji nowego użytkownika, możesz poprosić go o podanie wszelkich dodatkowych informacji o profilu, których potrzebujesz.

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

Gdy logujesz się przez Google, automatycznie uzyskujesz dostęp do wszystkich funkcji zabezpieczeń i infrastruktury Google, które chronią jego dane. Jednak w mało prawdopodobnym przypadku, gdy konto Google użytkownika zostanie przejęte lub wystąpi inne ważne zdarzenie związane z bezpieczeństwem, aplikacja również może być narażona na atak. Aby lepiej chronić swoje konta przed ważnymi zdarzeniami związanymi z bezpieczeństwem, włącz ochronę wszystkich kont, dzięki której będziesz otrzymywać alerty bezpieczeństwa od Google. Dzięki temu będziesz mieć wgląd w ważne zmiany dotyczące bezpieczeństwa konta Google użytkownika. Dzięki temu możesz podjąć odpowiednie działania w swojej usłudze, aby zabezpieczyć swoje konta.