Вход в связанный аккаунт для Android

Вход через связанный аккаунт позволяет пользователям, которые уже связали свой аккаунт Google с вашим сервисом, входить в одно нажатие. Это повышает удобство для пользователей, поскольку они могут войти в систему одним кликом, не вводя повторно имя пользователя и пароль. Это также снижает вероятность того, что пользователи создадут дублирующиеся аккаунты в вашем сервисе.

Вход через связанный аккаунт доступен в рамках процесса входа через One Tap на Android. Это значит, что вам не нужно импортировать отдельную библиотеку, если в вашем приложении уже включена функция One Tap.

В этом документе рассказывается, как изменить приложение Android, чтобы оно поддерживало вход через связанный аккаунт.

Принцип работы

  1. Вы включаете показ связанных аккаунтов при входе через One Tap.
  2. Если пользователь вошел в аккаунт Google и связал его с аккаунтом в вашем сервисе, будет возвращен токен идентификации для связанного аккаунта.
  3. Пользователь увидит запрос на вход через One Tap с возможностью войти в ваш сервис, используя связанный аккаунт.
  4. Если пользователь решит продолжить работу со связанным аккаунтом, токен идентификатора пользователя будет возвращен в ваше приложение. Вы сопоставляете его с токеном, который был отправлен на ваш сервер на шаге 2, чтобы идентифицировать вошедшего в аккаунт пользователя.

Настроить

Чтобы настроить вход через связанный аккаунт, подготовьте среду разработки и приложение.

Как настроить среду разработки

Установите на хост-компьютер последнюю версию сервисов Google Play:

  1. Откройте Android SDK Manager.
  1. В разделе SDK Tools найдите Сервисы Google Play.

  2. Если статус этих пакетов не "Установлено", выберите их и нажмите Install Packages (Установить пакеты).

Настройка приложения

  1. В файле build.gradle на уровне проекта добавьте репозиторий Google Maven в разделы buildscript и allprojects.

    buildscript {
        repositories {
            google()
        }
    }
    
    allprojects {
        repositories {
            google()
        }
    }
    
  2. Добавьте зависимости для Link with Google API в файл Gradle на уровне приложения, который обычно называется app/build.gradle:

    dependencies {
      implementation 'com.google.android.gms:play-services-auth:21.3.0'
    }
    

Измените приложение для Android, чтобы поддерживать вход через связанный аккаунт

В конце процесса входа в связанный аккаунт вашему приложению возвращается токен идентификатора. Перед входом пользователя необходимо проверить целостность токена идентификатора.

В примере кода ниже показано, как получить и проверить токен идентификации, а затем выполнить вход пользователя.

  1. Создайте действие, чтобы получить результат намерения входа

    Kotlin

      private val activityResultLauncher = registerForActivityResult(
        ActivityResultContracts.StartIntentSenderForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
          try {
            val signInCredentials = Identity.signInClient(this)
                                    .signInCredentialFromIntent(result.data)
            // Review the Verify the integrity of the ID token section for
            // details on how to verify the ID token
            verifyIdToken(signInCredential.googleIdToken)
          } catch (e: ApiException) {
            Log.e(TAG, "Sign-in failed with error code:", e)
          }
        } else {
          Log.e(TAG, "Sign-in failed")
        }
      }
    

    Java

      private final ActivityResultLauncher<IntentSenderResult>
        activityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartIntentSenderForResult(),
        result -> {
        If (result.getResultCode() == RESULT_OK) {
            try {
              SignInCredential signInCredential = Identity.getSignInClient(this)
                             .getSignInCredentialFromIntent(result.getData());
              verifyIdToken(signInCredential.getGoogleIdToken());
            } catch (e: ApiException ) {
              Log.e(TAG, "Sign-in failed with error:", e)
            }
        } else {
            Log.e(TAG, "Sign-in failed")
        }
    });
    
  2. Создание запроса на вход

    Kotlin

    private val tokenRequestOptions =
    GoogleIdTokenRequestOptions.Builder()
      .supported(true)
      // Your server's client ID, not your Android client ID.
      .serverClientId(getString("your-server-client-id")
      .filterByAuthorizedAccounts(true)
      .associateLinkedAccounts("service-id-of-and-defined-by-developer",
                               scopes)
      .build()
    

    Java

     private final GoogleIdTokenRequestOptions tokenRequestOptions =
         GoogleIdTokenRequestOptions.Builder()
      .setSupported(true)
      .setServerClientId("your-service-client-id")
      .setFilterByAuthorizedAccounts(true)
      .associateLinkedAccounts("service-id-of-and-defined-by-developer",
                                scopes)
      .build()
    
  3. Запустите намерение Sign-In Pending.

    Kotlin

     Identity.signInClient(this)
        .beginSignIn(
      BeginSignInRequest.Builder()
        .googleIdTokenRequestOptions(tokenRequestOptions)
      .build())
        .addOnSuccessListener{result ->
          activityResultLauncher.launch(result.pendingIntent.intentSender)
      }
      .addOnFailureListener {e ->
        Log.e(TAG, "Sign-in failed because:", e)
      }
    

    Java

     Identity.getSignInClient(this)
      .beginSignIn(
        BeginSignInRequest.Builder()
          .setGoogleIdTokenRequestOptions(tokenRequestOptions)
          .build())
      .addOnSuccessListener(result -> {
        activityResultLauncher.launch(
            result.getPendingIntent().getIntentSender());
    })
    .addOnFailureListener(e -> {
      Log.e(TAG, "Sign-in failed because:", e);
    });
    

Проверьте целостность токена идентификации

Использование клиентской библиотеки Google API

Для проверки токенов идентификации Google в рабочей среде рекомендуется использовать клиентскую библиотеку API Google для Java.

Java

  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.");
  }

Метод GoogleIdTokenVerifier.verify() проверяет подпись JWT, утверждение aud, утверждение iss и утверждение exp.

Если вам нужно убедиться, что токен идентификатора представляет аккаунт организации Google Workspace или Cloud, вы можете проверить утверждение hd, проверив доменное имя, возвращенное методом Payload.getHostedDomain().