Memproses login pengguna dengan kredensial yang mereka simpan

Gunakan klien login Sekali Ketuk guna meminta izin dari pengguna untuk mengambil salah satu kredensial yang mereka gunakan sebelumnya untuk masuk ke aplikasi Anda. Ini kredensial dapat berupa Akun Google atau kombinasi nama pengguna dan sandi yang mereka simpan dengan Google menggunakan Chrome, isi otomatis Android atau Smart Lock untuk Sandi.

UI login dengan sekali ketuk

Saat kredensial berhasil diambil, Anda dapat menggunakannya dengan lancar membuat pengguna login ke aplikasi Anda.

Jika pengguna belum menyimpan kredensial apa pun, tidak ada UI yang ditampilkan, dan Anda dapat memberikan pengalaman logout seperti biasa.

Di mana saya sebaiknya menggunakan login Sekali Ketuk?

Jika aplikasi Anda mengharuskan pengguna untuk login, tampilkan UI Sekali Ketuk di login layar. Hal ini dapat sangat membantu meskipun Anda sudah memiliki "Login dengan Google" karena UI Sekali Ketuk dapat dikonfigurasi untuk hanya menampilkan kredensial sebelumnya digunakan untuk masuk, hal ini dapat menjadi pengingat bagi pengguna yang jarang cara mereka masuk terakhir kali, dan mencegah mereka masuk secara tidak membuat akun baru dengan aplikasi Anda.

Jika login bersifat opsional untuk aplikasi Anda, pertimbangkan untuk menggunakan login Sekali Ketuk di layar yang memiliki pengalaman yang ditingkatkan dengan login. Misalnya, jika pengguna dapat menjelajahi konten dengan aplikasi saat logout, namun hanya dapat memposting komentar atau menambahkan item ke keranjang belanja setelah masuk, itu akan menjadi konteks yang masuk akal untuk Login Sekali Ketuk.

Aplikasi opsional untuk login juga harus menggunakan login Sekali Ketuk di layar login mereka, karena alasan yang disebutkan di atas.

Sebelum memulai

1. Mengonfigurasi klien login Sekali Ketuk

Anda dapat mengonfigurasi klien login Sekali Ketuk agar pengguna login dengan aplikasi tersimpan sandi, Akun Google tersimpan, atau keduanya. (Sebaiknya mendukung keduanya, untuk aktifkan pembuatan akun dengan sekali ketuk untuk pengguna baru dan login otomatis atau sekali ketuk sebanyak mungkin pengguna yang kembali.)

Jika aplikasi Anda menggunakan login berbasis sandi, gunakan setPasswordRequestOptions() untuk mengaktifkan permintaan kredensial sandi.

Jika aplikasi Anda menggunakan Login dengan Google, gunakan setGoogleIdTokenRequestOptions() untuk mengaktifkan dan mengonfigurasi permintaan token ID Google:

  • Tetapkan client ID server ke ID yang Anda buat di Google API konsol. Perhatikan bahwa ini adalah ID klien server Anda, bukan client ID Android Anda.

  • Konfigurasi klien untuk memfilter menurut akun yang diberi otorisasi. Jika Anda mengaktifkan klien Sekali Ketuk hanya meminta pengguna untuk login ke aplikasi Anda Akun Google yang telah mereka gunakan sebelumnya. Tindakan ini dapat membantu pengguna untuk login ketika mereka tidak yakin apakah mereka sudah memiliki akun atau Akun Google yang mereka gunakan, dan mencegah pengguna membuat file baru secara tidak sengaja akun dengan aplikasi Anda.

  • Jika Anda ingin membuat pengguna login secara otomatis, jika memungkinkan, aktifkan fitur tersebut dengan setAutoSelectEnabled(). Login otomatis dimungkinkan jika memenuhi kriteria berikut:

    • Pengguna memiliki tepat satu kredensial yang disimpan untuk aplikasi Anda. Artinya, satu sandi tersimpan atau satu Akun Google tersimpan.
    • Pengguna belum menonaktifkan login otomatis di setelan Akun Google mereka.
  • Meskipun opsional, sebaiknya Anda mempertimbangkan penggunaan nonce untuk meningkatkan keamanan login dan menghindari serangan replay. Gunakan setNonce menyertakan nonce dalam setiap permintaan. Lihat SafetyNet Mendapatkan nonce untuk saran dan detail tambahan tentang cara membuat 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. Memeriksa apakah ada pengguna yang login

Jika Aktivitas Anda dapat digunakan oleh pengguna yang login atau pengguna yang logout, periksa yang menunjukkan status pengguna sebelum menampilkan UI login Sekali Ketuk.

Anda juga harus melacak apakah pengguna telah menolak untuk menggunakannya Login Sekali Ketuk dengan menutup perintah atau mengetuk di luar perintah. Hal ini dapat sesederhana properti boolean Aktivitas Anda. (Lihat Berhenti menampilkan UI Sekali Ketuk, di bawah.)

3. Menampilkan UI login Sekali Ketuk

Jika pengguna tidak login dan belum menolak untuk menggunakan login Sekali Ketuk, panggil metode beginSignIn() objek klien, dan tambahkan pemroses ke Task yang ditampilkan. Aplikasi biasanya melakukan hal ini dalam metode onCreate() Aktivitas atau setelah transisi layar saat menggunakan arsitektur Aktivitas tunggal.

Klien Sekali Ketuk akan memanggil pemroses yang berhasil jika pengguna memiliki untuk aplikasi Anda. Di pemroses yang berhasil, dapatkan intent yang tertunda dari hasil Task dan teruskan ke startIntentSenderForResult() untuk memulai UI login Sekali Ketuk.

Jika pengguna tidak memiliki kredensial yang tersimpan, klien Sekali Ketuk akan memanggil pemroses kegagalan. Dalam kasus ini, Anda tidak perlu melakukan tindakan apa pun: Anda cukup melanjutkan menampilkan pengalaman aplikasi logout. Namun, jika Anda mendukung fitur Sekali Ketuk mendaftar, Anda dapat memulai alur tersebut di sini untuk pembuatan akun yang lancar pengalaman yang lancar bagi developer. Lihat Membuat akun baru dengan sekali ketuk.

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. Menangani respons pengguna

Respons pengguna terhadap dialog login Sekali Ketuk akan dilaporkan ke aplikasi Anda menggunakan metode onActivityResult() Aktivitas Anda. Jika pengguna memilih untuk {i>login<i}, hasilnya adalah kredensial yang disimpan. Jika pengguna menolak login, dengan menutup UI Sekali Ketuk atau mengetuk di luarnya, hasilnya akan ditampilkan dengan kode RESULT_CANCELED. Aplikasi Anda harus menangani kedua kemungkinan tersebut.

Login dengan kredensial yang diambil

Jika pengguna memilih untuk berbagi kredensial dengan aplikasi Anda, Anda bisa mengambilnya dengan meneruskan data intent dari onActivityResult() ke klien Sekali Ketuk Metode getSignInCredentialFromIntent(). Kredensial akan memiliki nilai bukan null googleIdToken jika pengguna membagikan kredensial Akun Google kepada aplikasi Anda, atau properti password non-null jika pengguna membagikan sandi tersimpan.

Gunakan kredensial tersebut untuk melakukan autentikasi dengan backend aplikasi Anda.

  • Jika pasangan nama pengguna dan sandi diambil, gunakan keduanya untuk login dengan cara yang sama seperti yang Anda lakukan jika pengguna memberikannya secara manual.
  • Jika kredensial Akun Google diambil, gunakan token ID untuk melakukan autentikasi dengan backend Anda. Jika Anda memilih untuk menggunakan nonce guna membantu menghindari replay akan memeriksa nilai respons di server backend Anda. Lihat Autentikasi dengan backend menggunakan 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) {
                    // ...
                }
            }
        }
    }
    // ...
}

Berhenti menampilkan UI Sekali Ketuk

Jika pengguna menolak login, panggilan ke getSignInCredentialFromIntent() akan menampilkan ApiException dengan kode status CommonStatusCodes.CANCELED. Jika ini terjadi, sebaiknya nonaktifkan UI login Sekali Ketuk untuk sementara jangan mengganggu pengguna Anda dengan perintah berulang. Contoh berikut menyelesaikan ini dengan mengatur properti pada Aktivitas, yang digunakannya untuk menentukan apakah menawarkan login Sekali Ketuk kepada pengguna; namun, Anda juga bisa menyimpan nilai untuk SharedPreferences atau gunakan metode lain.

Anda harus menerapkan pembatasan kapasitas untuk perintah login Sekali Ketuk. Jika tidak dilakukan, dan pengguna membatalkan beberapa perintah berturut-turut, aplikasi Sekali Ketuk tidak akan meminta konfirmasi pengguna selama 24 jam ke depan.

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. Menangani logout

Saat pengguna logout dari aplikasi, panggil metode signOut() klien Sekali Ketuk. Memanggil signOut() akan menonaktifkan login otomatis hingga pengguna login lagi.

Meskipun Anda tidak menggunakan login otomatis, langkah ini penting karena memastikan bahwa saat pengguna logout dari aplikasi, status autentikasi API layanan Play yang Anda gunakan juga akan direset.

Langkah berikutnya

Jika Anda mengonfigurasi klien Sekali Ketuk untuk mengambil kredensial Google, aplikasi Anda kini bisa mendapatkan token ID Google yang mewakili Akun Google. Pelajari cara menggunakan token ini pada backend.

Jika mendukung Login dengan Google, Anda juga dapat menggunakan klien Sekali Ketuk untuk menambahkan alur pembuatan akun yang lancar ke aplikasi Anda.