Войдите в учетную запись Google со старым паролем - как перенаправить на синюю страницу входа в Google? - PullRequest
0 голосов
/ 21 февраля 2019

Я внедрил Google Sign-In SDK в свое приложение, и оно работает нормально.Когда я нажимаю кнопку входа, открывается окно с уже сохраненными учетными записями.Выбор одной из этих учетных записей успешно завершает процесс входа в систему.

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


Я следовал инструкции Google "реализовать SDK для входа" и после вызова этих строк:

Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);

Я ловлю исключениес кодом состояния 12501 SIGN_IN_CANCELLED.

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

Вот шаги для воспроизведения:

  1. пользователь вошел в систему один раз
  2. диалоговое окно сохранило свои учетные данные
  3. тем временем пользователь изменил пароль своей учетной записи на www
  4. пользователь выбирает сохраненные учетные данные
  5. происходит несвязанный код ошибки).

Как я могу заставить пользователя перенаправить на эту синюю страницу входа в Google исохранить текущий поток?

Например, AliExpress каким-то образом справится с этим и перенаправит пользователя на синюю страницу с просьбой снова войти в систему.

enter image description here

Мой код мало чем отличается от инструкции Google.Это мой поток кода.Все начинаются с onClick():

В onClick() Метод:

// Logout before all operations
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
    mGoogleSignInClient.signOut();
}

// Call to sign in
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RequestCodes.RC_GOOGLE_SIGN_IN);

В onActivityResult Раздел:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");

    if (requestCode == RequestCodes.RC_GOOGLE_SIGN_IN) {

        try {

            // Call to take account data
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);

            // Fetch account data
            GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);

            Account account = googleSignInAccount.getAccount();

            // Calling to get short lived token
            String shortLivedToken = GoogleAuthUtil.getToken(mContext, account, "oauth2:" + Scopes.PROFILE + " " + Scopes.EMAIL);

            // Further calls here...

        } catch (ApiException e) {

            //https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes

            if (e.getStatusCode() == 12501) {
                Log.e(TAG, "SIGN_IN_CANCELLED");
            } else if (e.getStatusCode() == 12502) {
                Log.e(TAG, "SIGN_IN_CURRENTLY_IN_PROGRESS");
            } else if (e.getStatusCode() == 12500) {
                Log.e(TAG, "SIGN_IN_FAILED");
            } else {
                e.printStackTrace();
            }

        } catch (GoogleAuthException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

1 Ответ

0 голосов
/ 12 марта 2019

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

Краткий ответ

Вы все делаете правильно.Это рекомендуемый способ входа в учетную запись Google.К сожалению, в этом механизме нет фактического обратного вызова, чтобы указать, что на самом деле пошло не так в вашем случае Службы Google Play обрабатывают это, уведомляя пользователя о том, что его учетные данные устарели из-за уведомлений, которые вы можете увидеть ниже (сразу после изменения пароля).

notification

Я бы порекомендовал сообщить об ошибке при добавлении дополнительных кодов результатов для вашего дела на https://issuetracker.google.com, так как это кажется значительным улучшением.

Длинный ответ

Google использует API учетной записи Android , как и все остальные (вы можете попробовать сами).За кулисами это просто механизм поиска и хранения oauth-токенов.

Когда пароль был изменен, токен больше не действителен, и вы пытаетесь его использовать.

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

Например, AliExpress каким-то образом справится с этим и перенаправит пользователя на синюю страницу с просьбой подписать его.снова.

Aliexpress использует устаревший API .Как видите, диалоговое окно для выбора аккаунта имеет другой цвет и нет аватаров.API все еще можно использовать, но он может быть отключен в любое время (или нет).Я не рекомендую вам использовать это, но вот как это работает:

import com.google.android.gms.common.AccountPicker;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;

void chooseAccount() {
    Intent signInIntent = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
    startActivityForResult(signInIntent, REQ_CHOOSE_ACCOUNT);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == REQ_CHOOSE_ACCOUNT) {

        String email = data.getExtras().getString("authAccount");
        // better do this in background thread
        try {
            GoogleAuthUtil.getToken(this, new Account(email, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE), "oauth2:https://www.googleapis.com/auth/userinfo.profile");
        } catch (UserRecoverableAuthException recEx) {
            Intent recoverIntent = recEx.getIntent();
            // Will redirect to login activity
            startActivityForResult(recoverIntent, REQ_RECOVER);
        } catch (Exception e) {
            Log.d(TAG, "caught exception", e);
        }

    }
}

Надеюсь, это поможет!

UPD : новые API Google Play имеют ResolvableApiException , который расширяет ApiException, которую вы ловите.У него есть метод startResolutionForResult (), похожий на тот, который использовался в старых API.Но пакет, который вы получаете, не содержит информации о разрешении.

Bundle[{googleSignInStatus=Status{statusCode=unknown status code: 12501, resolution=null}}]

Если вы отправите сообщение об ошибке, опубликуйте его здесь, мы добавим его)

Вы также можете отобразить диалоговое окно «Выбор учетной записи» с помощью API Android по умолчанию (мин.API 23)

Приведенный ниже код можно использовать для отображения «диалога выбора учетной записи» с использованием стандартных API управления учетными записями Android .Это новое и (мы надеемся) некоторое время не будет устаревшим.

import android.accounts.Account;
import android.accounts.AccountManager;

// Unfortunately can be used only on API 23 and higher
Intent signInIntent = AccountManager.newChooseAccountIntent(
            null,
            null,
            new String[] { "com.google" },
            "Please select your account",
            null,
            null,
            new Bundle());

startActivityForResult(signInIntent, REQ_SELECT_ACCOUNT);

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQ_SELECT_ACCOUNT) {
            String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
            String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
            // now you can call GoogleAuthUtil as in example above
        }
    }

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

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

import android.accounts.Account;
import android.accounts.AccountManager;

try {
        // requires android.permission.GET_ACCOUNTS
        Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
        for (Account account : accounts) {
            Log.d(TAG, "account: " + account.name);
        }
    } catch (Exception e) {
        Log.i("Exception", "Exception:" + e);
    }

Заключение К сожалению, я не нашел других способов получить доступ к данным аккаунта Google, чтобы обойти ваше дело, используя современныеAPI входа в Google.Все расширенные API AccountManager требуют, чтобы у вас была та же подпись, что и у приложения владельца аккаунта (GMS - Google Mobile Services), что не соответствует действительности.Поэтому мы можем только запросить это у Google и надеяться, что это будет реализовано: (

...