Logowanie użytkowników przy użyciu zapisanych danych logowania

Użyj klienta logowania jednym dotknięciem, aby poprosić użytkownika o zgodę na pobranie danych jednego z danych logowania używanych wcześniej do logowania się w aplikacji. Te danymi uwierzytelniającymi może być konto Google lub kombinacja nazwa użytkownika i hasło zapisane w Google za pomocą Chrome, autouzupełniania na Androidzie lub Smart Lock Hasła.

Interfejs logowania jednym kliknięciem

Po pobraniu danych logowania możesz bez problemu z nich korzystać zalogować użytkownika w Twojej aplikacji.

Jeśli użytkownik nie zapisał żadnych danych logowania, nie wyświetli się żaden interfejs, nie będą działać tak samo jak bez logowania.

Gdzie mam korzystać z logowania jednym dotknięciem?

Jeśli Twoja aplikacja wymaga od użytkowników logowania się, wyświetl interfejs jednym dotknięciem podczas logowania ekranu. Może to być przydatne, nawet jeśli masz już funkcję „Zaloguj się przez Google” ponieważ interfejs One Tap można skonfigurować tak, aby wyświetlał tylko dane uwierzytelniające przez użytkowników logujących się wcześniej, możesz ustawić przypomnienie dla użytkowników, którzy rzadko jak się logował ostatnio, i zapobiec przypadkowemu tworzenia nowych kont za pomocą aplikacji.

Jeśli logowanie się w Twojej aplikacji jest opcjonalne, rozważ użycie na dowolnym ekran, na którym można wygodniej się zalogować. Jeśli na przykład użytkownicy mogą przeglądają treści w aplikacji po wylogowaniu się, ale mogą tylko publikować komentarze i dodawać do koszyka po zalogowaniu. Byłoby to rozsądnym kontekstem dla Logowanie jednym dotknięciem

Aplikacje opcjonalnego logowania powinny też korzystać z logowania jednym dotknięciem na ekranach logowania. z powodów podanych powyżej.

Zanim zaczniesz

1. Konfigurowanie klienta logowania jednym dotknięciem

Możesz skonfigurować klienta logowania jednym dotknięciem, aby logować użytkowników za pomocą zapisanych hasła, zapisane konta Google lub jedno z tych kont. (Zalecamy obsługę obu, włącz tworzenie kont jednym kliknięciem dla nowych użytkowników i logowanie automatyczne lub jednym dotknięciem dla jak największej liczby powracających użytkowników).

Jeśli Twoja aplikacja korzysta z logowania się przy użyciu hasła, użyj aplikacji setPasswordRequestOptions(), aby: włączyć żądania danych logowania.

Jeśli Twoja aplikacja używa Logowania przez Google, użyj aplikacji setGoogleIdTokenRequestOptions(), aby Włączanie i konfigurowanie żądań tokenów identyfikatora Google:

  • Ustaw identyfikator klienta serwera na identyfikator utworzony w interfejsach API Google konsola. Pamiętaj, że to identyfikator klienta serwera, a nie identyfikator identyfikator klienta Androida.

  • Skonfiguruj klienta w celu filtrowania według autoryzowanych kont. Po włączeniu użytkownik będzie musiał zalogować się w aplikacji za pomocą kont Google, które były już przez nie używane w przeszłości; Może to pomóc użytkownikom w logowaniu w sytuacji, gdy nie jest pewna, czy ma już konto używane przez nich konto Google, oraz zapobiega przypadkowemu utworzeniu nowych kont z aplikacją.

  • Jeśli chcesz, aby użytkownicy logowali się automatycznie, gdy jest to możliwe, włącz tę funkcję dzięki setAutoSelectEnabled(). Logowanie automatyczne jest możliwe, gdy spełnione są następujące kryteria:

    • Użytkownik ma zapisane dokładnie 1 dane logowania dla Twojej aplikacji. Oznacza to, że jedna zapisana hasła lub jednego zapisanego konta Google.
    • użytkownik nie wyłączył automatycznego logowania na swoim koncie. Ustawienia konta Google
  • Chociaż jest to opcjonalne, zalecamy rozważenie użycia liczby jednorazowej, aby poprawić bezpieczeństwo logowania i uniknąć ataków typu „replay”. Używaj setNonce , aby uwzględniać liczbę jednorazową w każdym żądaniu. Zobacz SafetyNet Uzyskiwanie liczby jednorazowej , gdzie znajdziesz sugestie i dodatkowe szczegóły dotyczące generowania liczby jednorazowej.

Java

public class YourActivity extends AppCompatActivity {
  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signInRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signInRequest = BeginSignInRequest.builder()
              .setPasswordRequestOptions(PasswordRequestOptions.builder()
                      .setSupported(true)
                      .build())
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.default_web_client_id))
                      // Only show accounts previously used to sign in.
                      .setFilterByAuthorizedAccounts(true)
                      .build())
              // Automatically sign in when exactly one credential is retrieved.
              .setAutoSelectEnabled(true)
              .build();
      // ...
  }
  // ...
}

Kotlin

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signInRequest = BeginSignInRequest.builder()
            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
                .setSupported(true)
                .build())
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Only show accounts previously used to sign in.
                    .setFilterByAuthorizedAccounts(true)
                    .build())
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()
        // ...
    }
    // ...
}

2. Sprawdzanie, czy użytkownik jest zalogowany

Jeśli informacje o Twojej aktywności mogą być dostępne zarówno dla zalogowanego, jak i niezalogowanego użytkownika, sprawdź stan użytkownika przed wyświetleniem interfejsu logowania jednym dotknięciem.

Sprawdzaj też, czy użytkownik odmówił już korzystania z usługi. Logowanie jednym dotknięciem przez zamknięcie potwierdzenia lub kliknięcie poza nim. Może to spowodować być tak prosta jak właściwość logiczna aktywności. (patrz poniżej, Wyłączanie wyświetlania interfejsu jednym dotknięciem).

3. Wyświetl interfejs logowania jednym dotknięciem

Jeśli użytkownik nie jest zalogowany i jeszcze nie odmówił logowania jednym dotknięciem, wywołaj metodę beginSignIn() obiektu klienta i dołącz detektory do Task. Aplikacje zwykle robią to w metodzie onCreate() aktywności lub po przejściach ekranu w architekturze z pojedynczą aktywnością.

Klient One Tap zadzwoni do detektora sukcesu, jeśli użytkownik ma jakieś zapisane dane logowania do aplikacji. W detektorze sukcesu pobierz intencję oczekującą z wynik funkcji Task i przekazać go do funkcji startIntentSenderForResult(), aby rozpocząć Interfejs logowania jednym dotknięciem.

Jeśli użytkownik nie ma żadnych zapisanych danych logowania, klient One Tap wywoła metodę detektor błędów. W takim przypadku nie musisz nic robić – możesz po prostu kontynuować i prezentuje aplikację bez logowania się na konto. Jeśli jednak obsługujesz funkcję One Tap rejestracji, możesz rozpocząć ten proces tutaj, aby utworzyć konto bez problemu i uzyskiwanie dodatkowych informacji. Zobacz Tworzenie nowych kont jednym kliknięciem.

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No saved credentials found. Launch the One Tap sign-up flow, or
                // do nothing and continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Kotlin

oneTapClient.beginSignIn(signInRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0, null)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No saved credentials found. Launch the One Tap sign-up flow, or
        // do nothing and continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. Obsługa odpowiedzi użytkownika

Odpowiedź użytkownika na prośbę o zalogowanie się jednym dotknięciem zostanie zgłoszona do aplikacji za pomocą metody onActivityResult() aktywności. Jeśli użytkownik zalogował się, w wyniku działania zostaną zapisane dane logowania. Jeśli użytkownik odmówił zalogowania się, zamykając interfejs jednym dotknięciem lub dotykając go na zewnątrz, zobaczysz z powrotem kod RESULT_CANCELED. Aplikacja musi obsługiwać obie możliwości.

Zaloguj się przy użyciu pobranych danych logowania

Jeśli użytkownik udostępnił dane logowania aplikacji, możesz je pobrać za pomocą: przekazując dane dotyczące intencji z aplikacji onActivityResult() do klienta One Tap Metoda getSignInCredentialFromIntent(). Dane logowania będą miały wartość inną niż null Właściwość googleIdToken, jeśli użytkownik udostępnił dane logowania do konta Google Twojej aplikacji lub niepustą właściwość password, jeśli użytkownik udostępnił zapisane hasło.

Użyj tych danych logowania, aby uwierzytelnić się w backendzie aplikacji.

  • Jeśli nazwa użytkownika i hasło zostały pobrane, użyj ich do zalogowania się jak gdyby użytkownik wpisał je ręcznie.
  • Jeśli dane logowania do konta Google zostały pobrane, użyj tokena identyfikatora do uwierzytelnienia z backendem. Jeśli używasz liczby jednorazowej, by uniknąć powtórek ataki sprawdzają wartość odpowiedzi na serwerze backendu. Zobacz Uwierzytelnij się z backendu za pomocą tokenów tożsamości.

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();
                  String username = credential.getId();
                  String password = credential.getPassword();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  } else if (password != null) {
                      // Got a saved username and password. Use them to authenticate
                      // with your backend.
                      Log.d(TAG, "Got password.");
                  }
              } 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
                    val username = credential.id
                    val password = credential.password
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        password != null -> {
                            // Got a saved username and password. Use them to authenticate
                            // with your backend.
                            Log.d(TAG, "Got password.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token or password!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
                }
            }
        }
    }
    // ...
}

Przestań wyświetlać interfejs jednym dotknięciem

Jeśli użytkownik odmówił zalogowania, połączenie z numerem getSignInCredentialFromIntent() zwróci żądanie ApiException z kodem stanu CommonStatusCodes.CANCELED. W takim przypadku należy tymczasowo wyłączyć interfejs logowania jednym dotknięciem, aby nie irytować użytkowników wielokrotnymi prośbami. Poniższy przykład zapewnia To przez ustawienie właściwości w Aktywności, która będzie używana do określania, czy oferowanie użytkownikowi logowania jednym dotknięciem; ale możesz też zapisać wartość SharedPreferences lub użyj innej metody.

Ważne jest wdrożenie własnego ograniczenia liczby żądań logowania jednym dotknięciem. Jeśli tego nie zrobisz, a użytkownik anuluje kilka promptów z rzędu, nie wyświetla komunikatu przez następne 24 godziny.

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 {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              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 {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

5. Obsługa wylogowania

Gdy użytkownik wyloguje się z aplikacji, wywołaj metodę signOut() klienta One Tap. Wywołanie signOut() powoduje wyłączenie automatycznego logowania, dopóki użytkownik nie zaloguje się ponownie.

Nawet jeśli nie korzystasz z logowania automatycznego, ten krok jest ważny, ponieważ stan uwierzytelniania każdego, kto wyloguje się z aplikacji Zresetowane zostaną również interfejsy API Usług Google Play, których używasz.

Dalsze kroki

Jeśli skonfigurowano klienta One Tap do pobierania danych logowania Google, możesz teraz pobierać tokeny tożsamości Google, które reprezentują Konta Google. Ucz się jak używać tych tokenów w backendzie.

Jeśli obsługujesz Logowanie przez Google, możesz też za pomocą klienta jednym dotknięciem dodać bezproblemowego procesu tworzenia konta.