Wdrażanie funkcji Zaloguj się przez Google

W tym przewodniku opisujemy, jak wdrożyć funkcję Zaloguj się przez Google. Obejmuje on te kroki:

  • Dodaj zależności do aplikacji.
  • Utwórz instancję CredentialManager.
  • Utwórz proces planszy dolnej.
  • Utwórz przepływ przycisku.
  • Obsługa odpowiedzi na żądanie logowania.
  • Obsługuj błędy.
  • Obsługa wylogowywania.

Dodawanie zależności do aplikacji

W pliku build.gradle modułu zadeklaruj zależności, używając najnowszej wersji Credential Managera, uwierzytelniania w Usługach Google Play i googleid:

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha02")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02")
    implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>")
}

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha02"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02"
    implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

Tworzenie instancji Menedżera danych logowania

Użyj kontekstu aplikacji lub aktywności, aby utworzyć obiekt CredentialManager.

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

Tworzenie przepływu planszy dolnej

Plansza dolna to wbudowany interfejs Credential Manager. Korzystanie z tego interfejsu zapewnia spójne działanie wszystkich metod uwierzytelniania, takich jak hasła, klucze dostępu i Zaloguj się przez Google.

Konfigurowanie prośby o zalogowanie się na wcześniej autoryzowanych kontach

Spróbuj wysłać żądanie logowania przez Google za pomocą GetGoogleIdOption, aby pobrać token identyfikacji Google użytkownika.

Te fragmenty kodu sprawdzają, czy konto jest autoryzowane.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(true)
    .setServerClientId(WEB_CLIENT_ID)
    .setAutoSelectEnabled(true)
    .setNonce(generateSecureRandomNonce())
    .build()

Obiekt żądania googleIdOption jest skonfigurowany w ten sposób:

  • Filtrowanie wcześniej autoryzowanych kont: aby pobrać autoryzowane konta, które były wcześniej używane do logowania się w aplikacji, ustaw setFilterByAuthorizedAccounts na true.

    Pamiętaj, że domyślna wartość parametru setFilterByAuthorizedAccounts to true, co oznacza, że domyślnie w interfejsie planszy dolnej wyświetlane są tylko wcześniej autoryzowane konta.

  • Ustaw identyfikator klienta serwera: ustaw parametr setServerClientId. webClientId to identyfikator klienta usługi internetowej skonfigurowany na potrzeby protokołu OAuth w projekcie Google Cloud podczas wykonywania wymagań wstępnych.

  • Włączanie logowania automatycznego (opcjonalnie): aby włączyć logowanie automatyczne dla powracających użytkowników, użyj setAutoSelectEnabled(true) i setFilterByAuthorizedAccounts(true). Dzięki temu użytkownicy aplikacji, którzy byli już wcześniej zalogowani, nie muszą wykonywać niepotrzebnych czynności.

    Logowanie automatyczne jest możliwe tylko wtedy, gdy spełnione są te kryteria:

    • na urządzeniu jest tylko jedno autoryzowane konto, które było wcześniej używane do logowania się w aplikacji na urządzeniu; Jeśli na urządzeniu jest kilka autoryzowanych kont, logowanie automatyczne jest wyłączone.
    • Użytkownik nie wylogował się z aplikacji podczas poprzedniej sesji.
    • Użytkownik nie wyłączył logowania automatycznego w ustawieniach konta Google.
  • Ustaw liczbę jednorazową (opcjonalnie): aby zwiększyć bezpieczeństwo, ustaw liczbę jednorazową na potrzeby weryfikacji po stronie serwera. Aby zapobiec atakom typu replay, możesz dołączyć liczbę jednorazową do weryfikacji po stronie serwera za pomocą setNonce(). Upewnij się, że kod po stronie serwera sprawdza, czy liczby jednorazowe żądania i odpowiedzi są identyczne.

    Aby wygenerować liczbę jednorazową, użyj funkcji podobnej do tej, która generuje kryptograficznie silną losową liczbę jednorazową o określonej długości i koduje ją za pomocą Base64:

fun generateSecureRandomNonce(byteLength: Int = 32): String {
    val randomBytes = ByteArray(byteLength)
    SecureRandom().nextBytes(randomBytes)
    return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}

Prośba o zalogowanie się

Sprawdź, czy użytkownik ma autoryzowane konto na urządzeniu, wywołując metodę getCredential:

val request: GetCredentialRequest = GetCredentialRequest.Builder()
    .addCredentialOption(googleIdOption)
    .build()

// Use an activity-based context to avoid undefined system UI
// launching behavior.
val mutableContext = MutableContextWrapper(activityContext)
coroutineScope {
    try {
        val result = credentialManager.getCredential(
            request = request,            
            context = mutableContext // Use MutableContextWrapper to avoid memory leak during configuration changes
        )
        handleSignIn(result)
    } catch (e: GetCredentialException) {
        // Handle failures
    }
}

Konfigurowanie prośby o zalogowanie się, gdy nie ma dostępnych autoryzowanych kont

Jeśli na urządzeniu nie ma autoryzowanych użytkowników Twojej aplikacji, CredentialManager zwraca NoCredentialException. W takim przypadku wyłącz filtr autoryzowanych kont, aby użytkownik mógł zarejestrować się za pomocą innego konta.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(false)
    .setServerClientId(WEB_CLIENT_ID)
    .setNonce(generateSecureRandomNonce())
    .build()

Następnie poproś o zalogowanie się w taki sam sposób jak w przypadku autoryzowanych kont.

Tworzenie przepływu przycisku

Użyj przycisku, jeśli chcesz, aby użytkownicy mogli korzystać z funkcji Zaloguj się przez Google w tych przypadkach:

  • Użytkownik zamknął interfejs dolnej planszy Credential Manager.
  • Na urządzeniu nie ma kont Google.
  • Konta istniejące na urządzeniu wymagają ponownego uwierzytelnienia.

Tworzenie interfejsu przycisku

Można to zrobić za pomocą przycisku Jetpack Compose, ale możesz też użyć wstępnie zatwierdzonej ikony marki ze strony Wytyczne dotyczące marki Zaloguj się przez Google.

Tworzenie procesu logowania

Utwórz żądanie logowania przez Google za pomocą GetSignInWithGoogleOption, aby pobrać token identyfikatora Google.

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
    serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
    .build()

Następnie poproś o zalogowanie się w podobny sposób jak w przypadku interfejsu planszy dolnej.

Tworzenie funkcji wspólnego logowania na potrzeby planszy dolnej i przycisku

Aby obsłużyć logowanie, wykonaj te czynności:

  1. Użyj funkcji getCredential() interfejsu CredentialManager. Jeśli odpowiedź jest prawidłowa, wyodrębnij CustomCredential, który powinien być typu GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.
  2. Przekonwertuj obiekt na GoogleIdTokenCredential za pomocą metody GoogleIdTokenCredential.createFrom().

  3. Zweryfikuj dane logowania na serwerze strony zależnej.

  4. Upewnij się, że odpowiednio obsługujesz błędy.

fun handleSign(result: GetCredentialResponse) {
    // Handle the successfully returned credential.
    val credential = result.credential

    when (credential) {
        is CustomCredential -> {
            if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                try {
                    // Use googleIdTokenCredential and extract the ID for server-side validation.
                    val googleIdTokenCredential = GoogleIdTokenCredential
                        .createFrom(credential.data)
                } catch (e: GoogleIdTokenParsingException) {
                    Log.e(TAG, "Received an invalid google id token response", e)
                }
            } else {
                // Catch any unrecognized credential type here.
                Log.e(TAG, "Unexpected type of credential")
            }
        }

        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential")
        }
    }
}

Obsługuj błędy

Przejrzyj błędy wymienione w sekcji Rozwiązywanie problemów, aby upewnić się, że kod obsługuje wszystkie możliwe scenariusze błędów.

Obsługa wylogowywania

Ważne jest, aby zapewnić użytkownikom mechanizm wylogowywania się z aplikacji. Na przykład użytkownik może mieć na urządzeniu kilka kont Google i zdecydować się na zalogowanie się z innego konta. Możesz to zrobić na przykład na stronie ustawień.

Dostawca danych logowania może przechowywać aktywną sesję danych logowania i używać jej do ograniczania opcji logowania w przypadku przyszłych żądań logowania. Może na przykład nadać aktywnym danym logowania priorytet nad innymi dostępnymi danymi logowania.

Gdy użytkownik wyloguje się z aplikacji, wywołaj metodę interfejsu API clearCredentialState(), aby wyczyścić bieżący stan danych logowania użytkownika u wszystkich dostawców danych logowania. Spowoduje to powiadomienie wszystkich dostawców danych logowania, że wszystkie zapisane sesje danych logowania dla danej aplikacji powinny zostać wyczyszczone, co zapewni użytkownikom pełne opcje logowania przy następnym logowaniu.