Utilizza il client di accesso One Tap per richiedere all'utente l'autorizzazione a recuperare una delle credenziali che ha utilizzato in precedenza per accedere alla tua app. Queste credenziali possono essere un Account Google o una combinazione di nome utente e password salvata con Google utilizzando Chrome, la compilazione automatica di Android o Smart Lock per le password.
Una volta recuperate correttamente, puoi utilizzarle per far accedere l'utente alla tua app senza problemi.
Se l'utente non ha salvato credenziali, non viene visualizzata alcuna UI e puoi fornire la normale esperienza di accesso non eseguito.
Dove devo utilizzare l'accesso One Tap?
Se la tua app richiede agli utenti di accedere, mostra l'interfaccia utente One Tap nella schermata di accesso. Questa opzione può essere utile anche se hai già un pulsante "Accedi con Google": poiché l'interfaccia utente One Tap può essere configurata per mostrare solo le credenziali utilizzate dall'utente in precedenza per accedere, può ricordare agli utenti che accedono di rado come hanno eseguito l'accesso l'ultima volta ed evitare che creino accidentalmente nuovi account con la tua app.
Se l'accesso è facoltativo per la tua app, ti consigliamo di utilizzare l'accesso One Tap su qualsiasi schermata che offra un'esperienza migliorata dall'accesso. Ad esempio, se gli utenti possono navigare tra i contenuti della tua app senza aver eseguito l'accesso, ma possono pubblicare commenti o aggiungere articoli a un carrello della spesa solo dopo aver eseguito l'accesso, questo è un contesto appropriato per l'accesso con un solo tocco.
Per gli stessi motivi sopra indicati, anche le app facoltative per l'accesso devono utilizzare l'accesso con One Tap nelle relative schermate di accesso.
Prima di iniziare
- Configura il progetto della console API di Google e il progetto Android come descritto in Iniziare a utilizzare l'accesso con un solo tocco.
- Se supporti l'accesso tramite password, ottimizza la tua app per la compilazione automatica (o utilizza Smart Lock per password) in modo che gli utenti possano salvare le proprie credenziali di accesso dopo aver eseguito l'accesso.
1. Configurare il client di accesso One Tap
Puoi configurare il client di accesso One Tap in modo che gli utenti accedano con le password salvate, con gli Account Google salvati o con entrambi. Ti consigliamo di supportare entrambi per consentire la creazione di account con un solo tocco per i nuovi utenti e l'accesso automatico o con un solo tocco per il maggior numero possibile di utenti di ritorno.
Se la tua app utilizza l'accesso con password, utilizza setPasswordRequestOptions()
per attivare le richieste di credenziali con password.
Se la tua app utilizza Accedi con Google, utilizza setGoogleIdTokenRequestOptions()
per attivare e configurare le richieste di token ID Google:
Imposta l'ID client del server sull'ID che hai creato nella console API di Google. Tieni presente che si tratta dell'ID client del server, non del tuo ID client Android.
Configura il client in modo che filtri in base agli account autorizzati. Se 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 sanno con certezza se hanno già un account o quale Account Google hanno utilizzato e non possono creare accidentalmente nuovi account con la tua app.
Se vuoi che gli utenti accedano automaticamente, se possibile, attiva la funzionalità con
setAutoSelectEnabled()
. L'accesso automatico è possibile se 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.
Sebbene facoltativo, ti consigliamo vivamente di utilizzare un nonce per migliorare la sicurezza di accesso ed evitare attacchi di replay. 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. Verificare se un utente ha eseguito l'accesso
Se la tua attività può essere utilizzata da un utente che ha eseguito l'accesso o da un utente che non ha eseguito l'accesso, controlla lo stato dell'utente prima di visualizzare l'interfaccia utente di accesso con un solo tocco.
Devi anche tenere traccia di eventuali rifiuti da parte dell'utente di utilizzare l'accesso con un solo tocco chiudendo la richiesta o toccando al di fuori. Può essere semplice come una proprietà booleana della tua attività. (vedi Interrompere la visualizzazione dell'interfaccia utente One Tap di seguito).
3. Visualizza l'interfaccia utente di accesso One Tap
Se l'utente non ha eseguito l'accesso e non ha già rifiutato di utilizzare l'accesso con un solo tocco, chiama il metodo beginSignIn()
dell'oggetto client e associa gli ascoltatori al valore beginSignIn()
restituito.Task
In genere le app eseguono questa operazione nel metodo onCreate()
dell'attività o dopo le transizioni tra le schermate quando viene utilizzata un'architettura con una sola attività.
Il client One Tap chiamerà l'ascoltatore di eventi di successo se l'utente ha salvato le credenziali per la tua app. Nell'ascoltatore di eventi di successo, 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à l'ascoltatore di errori. In questo caso, non è richiesta alcuna azione: puoi semplicemente continuare a mostrare l'esperienza dell'app quando non è eseguito l'accesso. Tuttavia, se supporti la registrazione con un solo tocco, puoi avviare questo flusso qui per un'esperienza di creazione dell'account senza problemi. Consulta Creare nuovi account con un solo 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 con un solo tocco verrà segnalata alla tua app utilizzando il metodo onActivityResult()
della tua 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 One Tap o toccando al di fuori, il risultato verrà restituito con il codice RESULT_CANCELED
. L'app deve gestire entrambe le possibilità.
Accedere con le credenziali recuperate
Se l'utente ha scelto di condividere le credenziali con la tua app, puoi recuperarle passando i dati dell'intent da onActivityResult()
al metodo getSignInCredentialFromIntent()
del client One Tap. La credenziale avrà una proprietà googleIdToken
non null se l'utente ha condiviso una credenziale dell'Account Google con la tua app o una proprietà password
non null se l'utente ha condiviso una password salvata.
Utilizza la credenziale per autenticarti con il backend della tua app.
- Se è stata recuperata una coppia di nome utente e password, utilizzala per accedere come faresti se l'utente li avesse forniti manualmente.
Se le credenziali dell'Account Google sono state recuperate, utilizza il token ID per autenticarti con il tuo backend. Se hai scelto di utilizzare un nonce per evitare attacchi di replay, controlla il valore di 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'interfaccia utente di One Tap
Se l'utente ha rifiutato di accedere, la chiamata a getSignInCredentialFromIntent()
lancerà un ApiException
con un codice di stato CommonStatusCodes.CANCELED
.
In questi casi, devi disattivare temporaneamente l'interfaccia utente di accesso con un solo tocco per non infastidire gli utenti con richieste ripetute. L'esempio seguente lo ottiene impostando una proprietà sull'attività, che viene utilizzata per determinare se offrire all'utente l'accesso con un solo tocco. Tuttavia, puoi anche salvare un valore in SharedPreferences
o utilizzare un altro metodo.
È importante implementare il proprio limite di frequenza delle richieste di accesso One Tap. In caso contrario, se un utente annulla più richieste di seguito, il client One Tap non lo chiederà nelle 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 esce 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, venga reimpostato anche lo stato di autenticazione di tutte le API di Google Play Services che utilizzi.
Passaggi successivi
Se hai configurato il client One Tap per recuperare le credenziali di Google, ora la tua app può ottenere 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 alla tua app flussi di creazione di account senza problemi.