Utilizza il client di accesso One Tap per richiedere all'utente l'autorizzazione a recuperare una delle credenziali utilizzate in precedenza per accedere alla tua app. Queste credenziali possono essere un Account Google o una combinazione nome utente-password salvata su Google tramite Chrome, compilazione automatica di Android o Smart Lock per password.
Una volta recuperate correttamente le credenziali, puoi utilizzarle per far accedere l'utente alla tua app senza problemi.
Se l'utente non ha salvato alcuna credenziale, non viene visualizzata alcuna UI e puoi fornire la normale esperienza di disconnessione.
Dove dovrei utilizzare l'accesso One Tap?
Se la tua app richiede agli utenti di accedere, visualizza l'UI di One Tap nella schermata di accesso. Questo può essere utile anche se hai già un pulsante "Accedi con Google": poiché l'UI di One Tap può essere configurata in modo da mostrare solo le credenziali utilizzate in precedenza dall'utente per l'accesso, può essere un promemoria per gli utenti che raramente accedono l'ultima volta che hanno eseguito l'accesso e impedire loro di creare accidentalmente nuovi account con la tua app.
Se l'accesso è facoltativo per la tua app, valuta la possibilità di utilizzare l'accesso One Tap su qualsiasi schermata che offre un'esperienza migliorata grazie all'accesso. Ad esempio, se gli utenti possono sfogliare i contenuti con la tua app senza eseguire l'accesso, ma possono solo pubblicare commenti o aggiungere articoli al carrello degli acquisti dopo aver eseguito l'accesso, sarebbe un contesto sensato per l'accesso One Tap.
Anche le app di accesso facoltative devono utilizzare l'accesso One Tap nelle relative schermate di accesso, per i motivi indicati sopra.
Prima di iniziare
- Configura il progetto Android e la console API di Google come descritto in Iniziare a utilizzare l'accesso con un tocco.
- Se supporti l'accesso basato su password, ottimizza l'app per la compilazione automatica (o utilizza Smart Lock per le password), in modo che gli utenti possano salvare le proprie credenziali dopo l'accesso.
1. Configurare il client di accesso One Tap
Puoi configurare il client di accesso One Tap per consentire agli utenti di accedere con password salvate, Account Google salvati o entrambi. Ti consigliamo di supportarli entrambi per attivare la creazione di account con un tocco per i nuovi utenti e l'accesso automatico o con un tocco per il maggior numero possibile di utenti di ritorno.
Se la tua app utilizza l'accesso basato su password, usa setPasswordRequestOptions()
per attivare le richieste di credenziali per le password.
Se la tua app utilizza Accedi con Google, usa setGoogleIdTokenRequestOptions()
per attivare e configurare le richieste di token ID Google:
Imposta l'ID client server sull'ID che hai creato nella console delle API di Google. Tieni presente che questo è l'ID client del tuo server, non il tuo ID client Android.
Configura il client in modo che filtri in base agli account autorizzati. Quando attivi questa opzione, il client One Tap chiede agli utenti di accedere alla tua app solo con gli Account Google che hanno già utilizzato in passato. In questo modo gli utenti possono accedere correttamente quando non sono sicuri di avere già un account o quale Account Google hanno utilizzato e impedisce agli utenti di creare accidentalmente nuovi account con la tua app.
Se vuoi che gli utenti accedano automaticamente quando possibile, abilita la funzionalità con
setAutoSelectEnabled()
. L'accesso automatico è possibile quando vengono soddisfatti i seguenti criteri:- L'utente ha esattamente una credenziale salvata per la tua app, ovvero una password salvata o un Account Google salvato.
- L'utente non ha disattivato l'accesso automatico nelle impostazioni dell'Account Google.
Anche se facoltativo, ti consigliamo vivamente di considerare l'utilizzo di un nonce per migliorare la sicurezza dell'accesso ed evitare attacchi di ripetizione. Utilizza setNonce per includere un nonce in ogni richiesta. Consulta la sezione Ottenere un nonce di SafetyNet per suggerimenti e ulteriori dettagli sulla generazione di un nonce.
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. Verifica la presenza di un utente che ha eseguito l'accesso
Se la tua attività può essere utilizzata da un utente che ha eseguito l'accesso o che non ha eseguito l'accesso, controlla lo stato dell'utente prima di visualizzare l'interfaccia utente di accesso One Tap.
Dovresti anche controllare se l'utente ha già rifiutato di utilizzare l'accesso One Tap chiudendo la richiesta o toccando all'esterno. Può essere una proprietà booleana semplice della tua Attività. Consulta la sezione Interrompere la visualizzazione dell'interfaccia utente One Tap di seguito.
3. Visualizzare l'interfaccia utente di accesso One Tap
Se l'utente non ha eseguito l'accesso e non ha già rifiutato di utilizzare l'accesso One Tap, chiama il metodo beginSignIn()
dell'oggetto client e collega i listener all'Task
che restituisce. In genere le app eseguono questa operazione nel metodo onCreate()
dell'attività o dopo le transizioni dello schermo quando si utilizza un'architettura single-Activity.
Il client One Tap chiamerà il listener se l'utente dispone di credenziali salvate per la tua app. In questo listener, recupera l'intent in attesa dal risultato Task
e passalo a startIntentSenderForResult()
per avviare l'interfaccia utente di accesso One Tap.
Se l'utente non ha credenziali salvate, il client One Tap chiamerà il listener di errori. In questo caso, non è necessaria alcuna azione: puoi semplicemente continuare a presentare l'esperienza di disconnessione dell'app. Tuttavia, se supporti la registrazione One Tap, puoi avviare il flusso qui per un'esperienza di creazione dell'account senza interruzioni. Vedi Creare nuovi account con un tocco.
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. Gestire la risposta dell'utente.
La risposta dell'utente alla richiesta di accesso One Tap verrà segnalata alla tua app
utilizzando il metodo onActivityResult()
dell'attività. Se l'utente ha scelto di accedere,
il risultato sarà una credenziale salvata. Se l'utente ha rifiutato di accedere, chiudendo l'interfaccia utente di One Tap o toccando all'esterno, il risultato verrà restituito con il codice RESULT_CANCELED
. La tua app deve gestire entrambe le possibilità.
Accedi con le credenziali recuperate
Se l'utente ha scelto di condividere le credenziali con la tua app, puoi recuperarle
passando i dati sugli intent da onActivityResult()
al metodo
getSignInCredentialFromIntent()
del client One Tap. La credenziale avrà una proprietà googleIdToken
con valore non null se l'utente ha condiviso una credenziale dell'Account Google con la tua app o una proprietà password
con valore non null se l'utente ha condiviso una password salvata.
Usa le credenziali per eseguire l'autenticazione con il backend dell'app.
- Se è stata recuperata una coppia di nome utente e password, utilizzali per accedere allo stesso modo che faresti se l'utente le avesse fornite manualmente.
Se sono state recuperate le credenziali dell'Account Google, utilizza il token ID per l'autenticazione con il backend. Se hai scelto di utilizzare un nonce per evitare gli attacchi di ripetizione, controlla il valore della risposta sul server di backend. Consulta Autenticarsi con un backend utilizzando i token ID.
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) { // ... } } } } // ... }
Interrompere la visualizzazione dell'UI di One Tap
Se l'utente ha rifiutato di accedere, la chiamata al numero getSignInCredentialFromIntent()
verrà generato ApiException
con codice di stato CommonStatusCodes.CANCELED
.
In questo caso, ti consigliamo di disattivare temporaneamente l'interfaccia utente di accesso One Tap in modo da non infastidire gli utenti con richieste ripetute. L'esempio seguente raggiunge questo obiettivo impostando una proprietà nell'attività, che utilizza per determinare se offrire all'utente l'accesso One Tap. Tuttavia, puoi anche salvare un valore in SharedPreferences
o utilizzare un altro metodo.
È importante implementare la limitazione della frequenza delle richieste di accesso One Tap. In caso contrario e un utente annulla diversi messaggi di seguito, il client One Tap non lo invierà per le 24 ore successive.
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. Gestire la disconnessione
Quando un utente si disconnette dalla tua app, chiama il metodo signOut()
del client One Tap.
La chiamata a signOut()
disattiva l'accesso automatico finché l'utente non accede di nuovo.
Anche se non utilizzi l'accesso automatico, questo passaggio è importante perché garantisce che, quando gli utenti escono dalla tua app, viene reimpostato anche lo stato di autenticazione di tutte le API di Play Services che utilizzi.
Passaggi successivi
Se hai configurato il client One Tap per recuperare le credenziali Google, la tua app ora può ottenere i token ID Google che rappresentano gli Account Google dei tuoi utenti. Scopri come utilizzare questi token nel backend.
Se supporti Accedi con Google, puoi anche utilizzare il client One Tap per aggiungere flussi per la creazione di account senza problemi alla tua app.