Użyj klienta logowania jednym dotknięciem, aby poprosić użytkownika o pozwolenie na pobranie danych uwierzytelniających, których użył wcześniej do zalogowania się w aplikacji. Mogą to być dane konta Google lub kombinacja nazwy użytkownika i hasła, które użytkownik zapisał w Google za pomocą Chrome, automatycznego wypełniania danych na Androidzie lub Smart Locka do haseł.
Po pomyślnym pobraniu danych logowania możesz użyć ich do bezproblemowego zalogowania użytkownika w aplikacji.
Jeśli użytkownik nie zapisał żadnych danych logowania, nie wyświetla się interfejs użytkownika, a Ty możesz zapewnić normalne logowanie.
Gdzie należy używać logowania jednym dotknięciem?
Jeśli aplikacja wymaga zalogowania, wyświetl interfejs One Tap na ekranie logowania. Może to być przydatne nawet wtedy, gdy masz już przycisk „Zaloguj się przez Google”. Interfejs logowania jednym dotknięciem można skonfigurować tak, aby wyświetlał tylko dane logowania, których użytkownik używał wcześniej. Dzięki temu możesz przypomnieć użytkownikom, jak ostatnio się logowali, i zapobiec przypadkowemu tworzeniu nowych kont w Twojej aplikacji.
Jeśli rejestracja w aplikacji jest opcjonalna, rozważ użycie funkcji rejestracji jednym kliknięciem na dowolnym ekranie, na którym rejestracja umożliwia korzystanie z ulepszonych funkcji. Jeśli na przykład użytkownicy mogą przeglądać treści w Twojej aplikacji, gdy są wylogowani, ale po zalogowaniu mogą tylko publikować komentarze lub dodawać produkty do koszyka, to jest to odpowiedni kontekst do logowania się za pomocą jednego kliknięcia.
Z powodów wymienionych powyżej aplikacje, które nie wymagają logowania, powinny również używać logowania jednym dotknięciem na ekranach logowania.
Zanim zaczniesz
- Skonfiguruj projekt interfejsów API Google i projekt na Androida zgodnie z opisem w artykule Pierwsze kroki z logowaniem za pomocą jednego kliknięcia.
- Jeśli obsługujesz logowanie z hasłem, zoptymalizuj swoją aplikację pod kątem automatycznego wypełniania pól (lub użyj funkcji Smart Lock na hasła), aby użytkownicy mogli zapisywać swoje dane logowania po zalogowaniu się.
1. Konfigurowanie klienta logowania jednym dotknięciem
Możesz skonfigurować klienta logowania jednym dotknięciem, aby użytkownicy logowali się za pomocą zapisanych haseł lub zapisanych kont Google. (Zalecane jest obsługowanie obu tych funkcji, aby umożliwić tworzenie kont jednym kliknięciem nowym użytkownikom oraz automatyczne logowanie lub logowanie jednym kliknięciem jak największej liczbie powracających użytkowników).
Jeśli Twoja aplikacja używa logowania z hasłem, użyj setPasswordRequestOptions()
, aby włączyć żądania danych logowania z hasłem.
Jeśli Twoja aplikacja korzysta z Logowania przez Google, użyj setGoogleIdTokenRequestOptions()
, aby włączyć i skonfigurować żądania tokena Google ID:
Ustaw identyfikator klienta serwera na identyfikator utworzony w Konsoli interfejsów API Google. Pamiętaj, że jest to identyfikator klienta serwera, a nie identyfikator klienta Androida.
Skonfiguruj klienta, aby filtrował według autoryzowanych kont. Gdy włączysz tę opcję, klient Logowanie jednym dotknięciem będzie prosić użytkowników tylko o logowanie się w aplikacji za pomocą kont Google, których używali już w przeszłości. Dzięki temu użytkownicy będą mogli się zalogować, gdy nie będą pewni, czy mają już konto lub jakiego konta Google używali. Zapobiegnie to też przypadkowemu tworzeniu nowych kont w Twojej aplikacji.
Jeśli chcesz, aby użytkownicy logowali się automatycznie, gdy to możliwe, włącz tę funkcję za pomocą
setAutoSelectEnabled()
. Automatyczne logowanie jest możliwe, gdy są spełnione te kryteria:- Użytkownik ma dokładnie 1 zapisany zestaw danych logowania do Twojej aplikacji. Oznacza to 1 zapisane hasło lub 1 zapisane konto Google.
- Użytkownik nie wyłączył logowania automatycznego w ustawieniach konta Google.
Zalecamy używanie identyfikatora jednorazowego, aby zwiększyć bezpieczeństwo logowania i uniknąć ataków polegających na odtwarzaniu danych. Użyj metody setNonce, aby dołączyć nonce do każdego żądania. Więcej informacji o generowaniu nonce znajdziesz w sekcji Uzyskiwanie nonce w dokumentacji SafetyNet.
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 Twoja aktywność może być używana przez zalogowanego lub niezalogowanego użytkownika, sprawdź jego stan przed wyświetleniem interfejsu logowania One Tap.
Musisz też śledzić, czy użytkownik odrzucił już logowanie za pomocą jednego kliknięcia, zamykając okno lub klikając poza nim. Może to być coś tak prostego jak logiczna właściwość aktywności. (patrz sekcja Zatrzymywanie wyświetlania interfejsu One Tap poniżej).
3. Wyświetlanie interfejsu logowania jednym dotknięciem
Jeśli użytkownik nie jest zalogowany i nie odrzucił już logowania za pomocą jednego kliknięcia, wywołaj metodę beginSignIn()
obiektu klienta i dołącz do zwracanego obiektu Task
obiekty typu Listener. Aplikacje zwykle robią to w metodzie onCreate()
aktywności lub po przejściach między ekranami w przypadku architektury z jedną aktywnością.
Klient One Tap wywoła metodę success listener, jeśli użytkownik ma zapisane dane logowania do Twojej aplikacji. W tej metodzie odbierz oczekujący zamiar z wyniku Task
i przekaż go do startIntentSenderForResult()
, aby uruchomić interfejs logowania One Tap.
Jeśli użytkownik nie ma zapisanych danych logowania, klient One Tap wywoła odbiornik niepowodzenia. W takim przypadku nie musisz nic robić: możesz po prostu kontynuować korzystanie z aplikacji w trybie niezalogowanym. Jeśli jednak obsługujesz rejestrację One Tap, możesz rozpocząć ten proces tutaj, aby ułatwić użytkownikom tworzenie konta. Zobacz, jak tworzyć nowe konta za pomocą jednego kliknięcia.
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 monit logowania One Tap zostanie przekazana do Twojej aplikacji za pomocą metody onActivityResult()
aktywności. Jeśli użytkownik zdecyduje się na zalogowanie, zapisze dane logowania. Jeśli użytkownik odmówi zalogowania się, na przykład przez zamknięcie interfejsu One Tap lub kliknięcie poza nim, wynik zostanie zwrócony z kodem RESULT_CANCELED
. Twoja aplikacja musi obsługiwać obie te możliwości.
Logowanie się przy użyciu odzyskanych danych logowania
Jeśli użytkownik zdecyduje się udostępnić dane logowania aplikacji, możesz je pobrać, przekazując dane intencji z onActivityResult()
do metody getSignInCredentialFromIntent()
klienta One Tap. Jeśli użytkownik udostępnił Twojej aplikacji dane logowania do konta Google, będą one miały niepustą właściwość googleIdToken
. Jeśli użytkownik udostępnił zapisane hasło, będą one miały niepustą właściwość password
.
Użyj danych uwierzytelniających, aby uwierzytelnić się w backendzie aplikacji.
- Jeśli udało się pobrać parę nazwy użytkownika i hasła, użyj ich do zalogowania się w taki sam sposób, jak wtedy, gdy użytkownik podał je ręcznie.
Jeśli dane logowania do konta Google zostały pobrane, użyj tokenu identyfikacyjnego do uwierzytelnienia na zapleczu. Jeśli z powodu unikania ataków polegających na odtwarzaniu danych korzystasz z nonce, sprawdź wartość odpowiedzi na serwerze zaplecza. Zapoznaj się z artykułem Uwierzytelnianie przy użyciu 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 logowania jednym dotknięciem,
Jeśli użytkownik odmówi zalogowania się, wywołanie metody getSignInCredentialFromIntent()
zwróci wartość ApiException
z kodem stanu CommonStatusCodes.CANCELED
.
W takim przypadku tymczasowo wyłącz interfejs logowania za pomocą jednego kliknięcia, aby nie irytować użytkowników powtarzającymi się prośbami. W tym przykładzie jest to osiągane przez ustawienie właściwości w działalności, która służy do określenia, czy użytkownikowi należy zaoferować logowanie za pomocą funkcji One Tap. Możesz też zapisać wartość w pliku SharedPreferences
lub użyć innej metody.
Ważne jest, aby wdrożyć własne ograniczenie szybkości wyświetlania promptów logowania jednym dotknięciem. Jeśli tego nie zrobisz, a użytkownik anuluje kilka kolejnych próśb o dostęp, klient One Tap nie będzie wyświetlać próśb przez kolejne 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. Wylogowanie
Gdy użytkownik wyloguje się z aplikacji, wywołaj metodę signOut()
klienta One Tap.
Wywołanie funkcji signOut()
powoduje wyłączenie automatycznego logowania, dopóki użytkownik nie zaloguje się ponownie.
Nawet jeśli nie używasz automatycznego logowania, ten krok jest ważny, ponieważ zapewnia, że gdy użytkownicy wylogują się z aplikacji, stan uwierzytelniania wszystkich interfejsów API usług Google Play, których używasz, zostanie zresetowany.
Dalsze kroki
Jeśli skonfigurujesz klienta One Tap tak, aby pobierał poświadczenia Google, Twoja aplikacja będzie mogła pobierać tokeny identyfikatora Google, które reprezentują konta Google użytkowników. Dowiedz się, jak użyć tych tokenów na zapleczu.
Jeśli obsługujesz logowanie Google, możesz też użyć klienta One Tap, aby dodać do aplikacji płynne procesy tworzenia konta.