Android: вход в Google — список токенов учетных данных всегда пуст

Я реализую вход в Google Smart Lock для автоматического входа пользователя без ввода, однако я сталкиваюсь с проблемой, что список токенов (getIdTokens), возвращаемый в списке токенов объекта учетных данных, всегда пуст даже после «успешного» связь. В какой момент объект учетных данных фактически заполняется списком токенов?

Я использую этот пример для создания кода:

https://github.com/googlesamples/android-credentials/blob/master/credentials-signin/app/src/main/java/com/google/example/credentialssignin/MainActivity.java#L101

private void googleSilentSignIn() {
        // Try silent sign-in with Google Sign In API
        OptionalPendingResult<GoogleSignInResult> opr =
                Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
        if (opr.isDone()) {
            GoogleSignInResult gsr = opr.get();
            handleGoogleSignIn(gsr);
        } else {
            opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                @Override
                public void onResult(GoogleSignInResult googleSignInResult) {
                    handleGoogleSignIn(googleSignInResult);
                }
            });
        }
    }


 private void handleGoogleSignIn(GoogleSignInResult gsr) {
        Timber.i("handleGoogleSignIn:" + (gsr == null ? "null" : gsr.getStatus()));

        boolean isSignedIn = (gsr != null) && gsr.isSuccess();
        if (isSignedIn) {
            // Display signed-in UI
            GoogleSignInAccount gsa = gsr.getSignInAccount();
            String status = String.format("Signed in as %s (%s)", gsa.getDisplayName(),
                    gsa.getEmail());

            Timber.d("handleGoogleSignIn %s", status);

            // Save Google Sign In to SmartLock
            Credential credential = new Credential.Builder(gsa.getEmail())
                    .setAccountType(IdentityProviders.GOOGLE)
                    .setName(gsa.getDisplayName())
                    .setProfilePictureUri(gsa.getPhotoUrl())
                    .build();

            saveCredentialIfConnected(credential);

            Timber.d("handleGoogleSignIn: credential tokens was %s", credential.getIdTokens().toString());
}
}

  private void requestCredentials(final boolean shouldResolve, boolean onlyPasswords) {
    Timber.d("requestCredentials");

    CredentialRequest.Builder crBuilder = new CredentialRequest.Builder()
            .setPasswordLoginSupported(true);

    if (!onlyPasswords) {
        crBuilder.setAccountTypes(IdentityProviders.GOOGLE);
    }

    Auth.CredentialsApi.request(mGoogleApiClient, crBuilder.build()).setResultCallback(
            new ResultCallback<CredentialRequestResult>() {
                @Override
                public void onResult(CredentialRequestResult credentialRequestResult) {
                    Status status = credentialRequestResult.getStatus();

                    if (status.isSuccess()) {
                        // Auto sign-in success

                        Timber.d("requestCredentials:onsuccess with token size %d", credentialRequestResult.getCredential().getIdTokens().size() );

                        handleCredential(credentialRequestResult.getCredential());
                    } else if (status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED
                            && shouldResolve) {
                        // Getting credential needs to show some UI, start resolution
                        resolveResult(status, RC_CREDENTIALS_READ);
                    }
                }
            });
}

@Override
public void onStart() {
    super.onStart();
    if (!mIsResolving) {
        requestCredentials(true /* shouldResolve */, false /* onlyPasswords */);
    }
}


private void handleCredential(Credential credential) {

        Timber.i("handleCredential with %s %s %s %s %s", credential.getId(), credential.getAccountType(), credential.getGeneratedPassword(), credential.getName(), credential.getPassword());

        mCredential = credential;

        if (IdentityProviders.GOOGLE.equals(credential.getAccountType())) {
            // Google account, rebuild GoogleApiClient to set account name and then try
            buildGoogleApiClient(credential.getId());
            googleSilentSignIn();
        }
}



Ответы (2)


getIdTokens() в объекте учетных данных должен возвращать список, содержащий токен OpenID Connect ID, если учетные данные были получены с помощью метода Auth.CredentialsApi.request() или Auth.CredentialsApi.getHintPickerIntent() и учетные данные соответствуют учетной записи Google, на которой выполнен вход на устройстве с запущенными сервисами Play Services 8+.

Обратите внимание, что .setAccountTypes(IdentityProviders.GOOGLE) должен быть включен при построении запроса:

    CredentialRequest request = new CredentialRequest.Builder()
            .setAccountTypes(IdentityProviders.GOOGLE)
            .setSupportsPasswordLogin(true)
            .build();

или при получении подсказки, если сохраненные учетные данные недоступны:

    HintRequest hintRequest = new HintRequest.Builder()
            .setAccountTypes(IdentityProviders.GOOGLE)
            .setEmailAddressIdentifierSupported(true)
            .build();

Токена идентификатора не будет, если учетные данные созданы с помощью Credential.Builder (как показано в части кода в вопросе) или если учетные данные не соответствуют адресу электронной почты учетной записи Google на устройстве.

Итак, что нужно проверить:

  • протестировать на устройстве с последней версией Play Services (8.4)

  • убедитесь, что полученные учетные данные соответствуют учетной записи Google, в которую выполнен вход на устройстве, и что учетная запись находится в хорошем состоянии (синхронизируется, получает электронные письма, не требует повторного ввода пароля и т. д.).

  • убедитесь, что полученные учетные данные были ранее сохранены в приложении или на связанном веб-сайте (через диспетчер паролей Chrome) или получены из HintRequest, созданного с помощью .setAccountType(IdentityProviders.GOOGLE)

Если у вас по-прежнему возникают проблемы с получением токена идентификатора, оставьте комментарий с подробной информацией о вашей среде.

person Steven    schedule 31.12.2015

Я нашел решение в googlesamples/android-credentials на GitHub, добавив .setIdTokenRequested(true)

CredentialRequest credentialRequest = new CredentialRequest.Builder()
                            .setPasswordLoginSupported(true)
                            .setAccountTypes(IdentityProviders.GOOGLE)
                            .setIdTokenRequested(true)
                            .build();
person user1795683    schedule 26.12.2017