Вход в связанную учетную запись для Android

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

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

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

Как это работает

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

Настраивать

Настройте среду разработки

Получите новейшие сервисы Google Play на своем хосте разработки:

  1. Откройте Android SDK Manager .
  1. В разделе «Инструменты SDK» найдите сервисы Google Play .

  2. Если статус этих пакетов не «Установлен», выберите их оба и нажмите «Установить пакеты» .

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

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

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

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

Измените свое приложение Android для поддержки входа в систему через связанную учетную запись.

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

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

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

    Котлин

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

    Джава

      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. Создание запроса на вход

    Котлин

    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()
    

    Джава

     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. Запустите намерение «Ожидание входа в систему»

    Котлин

     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)
      }
    

    Джава

     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. Используйте открытые ключи Google (доступные в формате JWK или PEM ) для проверки подписи токена. Эти ключи регулярно меняются; проверьте заголовок Cache-Control в ответе, чтобы определить, когда вам следует получить их снова.
  • Значение aud в токене идентификатора равно одному из идентификаторов клиента вашего приложения. Эта проверка необходима для предотвращения использования токенов идентификатора, выданных вредоносному приложению, для доступа к данным об одном и том же пользователе на внутреннем сервере вашего приложения.
  • Значение iss в токене идентификатора accounts.google.com или https://accounts.google.com .
  • Время истечения срока действия ( exp ) токена идентификатора не прошло.
  • Если вам необходимо убедиться, что токен идентификатора представляет учетную запись организации Google Workspace или Cloud, вы можете проверить утверждение hd , которое указывает размещенный домен пользователя. Это необходимо использовать при ограничении доступа к ресурсу только для членов определенных доменов. Отсутствие этого утверждения указывает на то, что учетная запись не принадлежит домену, размещенному в Google.

Вместо написания собственного кода для выполнения этих шагов проверки мы настоятельно рекомендуем использовать клиентскую библиотеку API Google для вашей платформы или библиотеку JWT общего назначения. Для разработки и отладки вы можете вызвать нашу конечную точку проверки tokeninfo .

,

Чтобы убедиться, что токен действителен, убедитесь, что выполняются следующие критерии:

  • Идентификационный токен правильно подписан Google. Используйте открытые ключи Google (доступные в формате JWK или PEM ) для проверки подписи токена. Эти ключи регулярно меняются; проверьте заголовок Cache-Control в ответе, чтобы определить, когда вам следует получить их снова.
  • Значение aud в токене идентификатора равно одному из идентификаторов клиента вашего приложения. Эта проверка необходима для предотвращения использования токенов идентификатора, выданных вредоносному приложению, для доступа к данным об одном и том же пользователе на внутреннем сервере вашего приложения.
  • Значение iss в токене идентификатора accounts.google.com или https://accounts.google.com .
  • Время истечения срока действия ( exp ) токена идентификатора не прошло.
  • Если вам необходимо убедиться, что токен идентификатора представляет учетную запись организации Google Workspace или Cloud, вы можете проверить утверждение hd , которое указывает размещенный домен пользователя. Это необходимо использовать при ограничении доступа к ресурсу только для членов определенных доменов. Отсутствие этого утверждения указывает на то, что учетная запись не принадлежит домену, размещенному в Google.

Вместо написания собственного кода для выполнения этих шагов проверки мы настоятельно рекомендуем использовать клиентскую библиотеку API Google для вашей платформы или библиотеку JWT общего назначения. Для разработки и отладки вы можете вызвать нашу конечную точку проверки tokeninfo .

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

Использование клиентской библиотеки Google API Java — рекомендуемый способ проверки токенов Google ID в производственной среде.

Джава

  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() .

Вызов конечной точки tokeninfo

Простой способ проверить подпись токена идентификатора для отладки — использовать конечную точку tokeninfo . Вызов этой конечной точки включает в себя дополнительный сетевой запрос, который выполняет большую часть проверки за вас, пока вы тестируете правильную проверку и извлечение полезной нагрузки в своем собственном коде. Он не подходит для использования в рабочем коде, поскольку запросы могут регулироваться или иным образом подвергаться периодическим ошибкам.

Чтобы проверить токен идентификатора с помощью конечной точки tokeninfo , выполните HTTPS-запрос POST или GET к конечной точке и передайте свой токен идентификатора в параметре id_token . Например, чтобы проверить токен «XYZ123», выполните следующий запрос GET:

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

Если токен правильно подписан и утверждения iss и exp имеют ожидаемые значения, вы получите ответ HTTP 200, тело которого содержит утверждения токена идентификатора в формате JSON. Вот пример ответа:

{
 // 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"
}

Если вам необходимо убедиться, что токен идентификатора представляет учетную запись Google Workspace, вы можете проверить утверждение hd , которое указывает размещенный домен пользователя. Это необходимо использовать при ограничении доступа к ресурсу только для членов определенных доменов. Отсутствие этого утверждения указывает на то, что учетная запись не принадлежит домену, размещенному в Google Workspace.

,

Вызов конечной точки tokeninfo

Простой способ проверить подпись токена идентификатора для отладки — использовать конечную точку tokeninfo . Вызов этой конечной точки включает в себя дополнительный сетевой запрос, который выполняет большую часть проверки за вас, пока вы тестируете правильную проверку и извлечение полезной нагрузки в своем собственном коде. Он не подходит для использования в рабочем коде, поскольку запросы могут регулироваться или иным образом подвергаться периодическим ошибкам.

Чтобы проверить токен идентификатора с помощью конечной точки tokeninfo , выполните HTTPS-запрос POST или GET к конечной точке и передайте свой токен идентификатора в параметре id_token . Например, чтобы проверить токен «XYZ123», выполните следующий запрос GET:

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

Если токен правильно подписан и утверждения iss и exp имеют ожидаемые значения, вы получите ответ HTTP 200, тело которого содержит утверждения токена идентификатора в формате JSON. Вот пример ответа:

{
 // 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"
}

Если вам необходимо убедиться, что токен идентификатора представляет учетную запись Google Workspace, вы можете проверить утверждение hd , которое указывает размещенный домен пользователя. Это необходимо использовать при ограничении доступа к ресурсу только для членов определенных доменов. Отсутствие этого утверждения указывает на то, что учетная запись не принадлежит домену, размещенному в Google Workspace.