Uwierzytelniaj za pomocą OpenID Connect na urządzeniu z Androidem

Jeśli masz już wersję Firebase Authentication with Identity Platform, możesz uwierzytelniać użytkowników Firebase za pomocą wybranego dostawcy obsługującego standard OpenID Connect (OIDC). Dzięki temu możesz używać dostawców tożsamości, którzy nie są obsługiwani natywnie przez Firebase.

Zanim zaczniesz

Aby logować użytkowników za pomocą dostawcy OIDC, musisz najpierw zebrać od niego te informacje:

  • Identyfikator klienta: ciąg znaków, który jest niepowtarzalny dla dostawcy i identyfikuje Twoją aplikację. Dostawca może przypisać inny identyfikator klienta dla każdej obsługiwanej platformy. Jest to jedna z wartości w oświadczeniu aud w tokenach identyfikacyjnych wydanych przez dostawcę.

  • Klucz klienta: tajny ciąg znaków, którego dostawca używa do potwierdzenia własności identyfikatora klienta. W przypadku każdego identyfikatora klienta musisz podać odpowiadający mu klucz klienta. (Ta wartość jest wymagana tylko wtedy, gdy używasz procesu kodu autoryzacji, który jest zdecydowanie zalecany).

  • Wystawca: ciąg znaków identyfikujący dostawcę. Ta wartość musi być adresem URL, który po dodaniu /.well-known/openid-configuration wskazuje lokalizację dokumentu OIDC dostawcy. Jeśli na przykład wystawcą jesthttps://auth.example.com, dokument informacyjny musi być dostępny pod adresemhttps://auth.example.com/.well-known/openid-configuration.

Gdy już je uzyskasz, włącz OpenID Connect jako usługę logowania w projekcie Firebase:

  1. Dodaj Firebase do projektu na Androida.

  2. Jeśli nie masz jeszcze dostępu do Firebase Authentication with Identity Platform, uaktualnij projekt. Uwierzytelnianie OpenID Connect jest dostępne tylko w uaktualnionych projektach.

  3. Na stronie Dostawcy logowania w konsoli Firebase kliknij Dodaj nowego dostawcę, a potem OpenID Connect.

  4. Wybierz, czy chcesz użyć przepływu kodu autoryzacji czy przepływu niejawnego uwierzytelniania.

    Jeśli Twój dostawca obsługuje ten proces, zawsze używaj go. Procedura domyślna jest mniej bezpieczna i zdecydowanie odradzamy jej używanie.

  5. Nazwij tego dostawcę. Zapisz wygenerowany identyfikator dostawcy: coś w stylu oidc.example-provider. Potrzebujesz tego identyfikatora, aby dodać do aplikacji kod logowania.

  6. Podaj identyfikator klienta, tajny klucz klienta i ciąg znaków wystawcy dostawcy. Te wartości muszą dokładnie odpowiadać wartościom przypisanym przez dostawcę.

  7. Zapisz zmiany.

Obsługa procesu logowania za pomocą pakietu SDK Firebase

Jeśli tworzysz aplikację na Androida, najłatwiej uwierzytelnić użytkowników za pomocą Firebase przy użyciu dostawcy OIDC, jeśli przekażesz cały proces logowania do pakietu SDK Firebase na Androida.

Aby obsłużyć proces logowania za pomocą pakietu Firebase Android SDK, wykonaj te czynności:

  1. Utwórz instancję klasy OAuthProvider za pomocą narzędzia Builder z identyfikatorem dostawcy

    Kotlin

    val providerBuilder = OAuthProvider.newBuilder("oidc.example-provider")

    Java

    OAuthProvider.Builder providerBuilder = OAuthProvider.newBuilder("oidc.example-provider");

  2. Opcjonalnie: określ dodatkowe niestandardowe parametry OAuth, które chcesz wysłać z prośbą OAuth.

    Kotlin

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com")

    Java

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com");

    Skontaktuj się z dostawcą usługi OIDC, aby poznać obsługiwane parametry. Pamiętaj, że za pomocą parametru setCustomParameters() nie możesz przekazywać parametrów wymaganych przez Firebase. Są to: client_id, response_type, redirect_uri, state, scope i response_mode.

  3. Opcjonalnie: określ dodatkowe zakresy OAuth 2.0 poza podstawowym profilem, o które chcesz poprosić dostawcę usługi uwierzytelniania.

    Kotlin

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    providerBuilder.scopes = listOf("mail.read", "calendars.read")

    Java

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    List<String> scopes =
            new ArrayList<String>() {
                {
                    add("mail.read");
                    add("calendars.read");
                }
            };
    providerBuilder.setScopes(scopes);

    Skontaktuj się z dostawcą OIDC, aby dowiedzieć się, jakie zakresy są używane.

  4. Uwierzytelnij się w Firebase, używając obiektu dostawcy OAuth. Pamiętaj, że w odróżnieniu od innych operacji FirebaseAuth ta operacja przejmie kontrolę nad interfejsem, wyświetlając niestandardową kartę Chrome. W związku z tym nie odwołuj się do aktywności w dołączonych elementach OnSuccessListenerOnFailureListener, ponieważ zostaną one natychmiast odłączone, gdy operacja uruchomi interfejs użytkownika.

    Najpierw sprawdź, czy nie dotarła do Ciebie już odpowiedź. Logowanie się w ten sposób powoduje, że Twoja aktywność jest wykonywana w tle, co oznacza, że system może ją wykorzystać podczas procesu logowania. Aby mieć pewność, że użytkownik nie będzie musiał powtarzać próby, sprawdź, czy wynik nie jest już dostępny.

    Aby sprawdzić, czy nie ma oczekujących wyników, zadzwoń pod numer getPendingAuthResult:

    Kotlin

    val pendingResultTask = firebaseAuth.pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener {
                // User is signed in.
                // IdP data available in
                // authResult.getAdditionalUserInfo().getProfile().
                // The OAuth access token can also be retrieved:
                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                // The OAuth secret can be retrieved by calling:
                // ((OAuthCredential)authResult.getCredential()).getSecret().
            }
            .addOnFailureListener {
                // Handle failure.
            }
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Java

    Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                                // IdP data available in
                                // authResult.getAdditionalUserInfo().getProfile().
                                // The OAuth access token can also be retrieved:
                                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                                // The OAuth secret can be retrieved by calling:
                                // ((OAuthCredential)authResult.getCredential()).getSecret().
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Aby rozpocząć proces logowania, zadzwoń pod numer startActivityForSignInWithProvider:

    Kotlin

    firebaseAuth
        .startActivityForSignInWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is signed in.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // ((OAuthCredential)authResult.getCredential()).getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    firebaseAuth
            .startActivityForSignInWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // ((OAuthCredential)authResult.getCredential()).getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  5. Powyższe przykłady koncentrują się na procesach logowania, ale za pomocą funkcji startActivityForLinkWithProvider możesz też połączyć dostawcę OIDC z dotychczasowym użytkownikiem. Możesz na przykład powiązać z tym samym użytkownikiem wielu dostawców, aby mógł się zalogować za pomocą dowolnego z nich.

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // Provider credential is linked to the current user.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // authResult.getCredential().getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // authResult.getCredential().getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForLinkWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Provider credential is linked to the current user.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // authResult.getCredential().getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // authResult.getCredential().getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  6. Tego samego schematu można używać w przypadku funkcji startActivityForReauthenticateWithProvider, która umożliwia pobieranie nowych danych logowania na potrzeby operacji narażonych na wyciek danych, które wymagają niedawnego zalogowania się.

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is re-authenticated with fresh tokens and
                            // should be able to perform sensitive operations
                            // like account deletion and email or password
                            // update.
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

Ręczne przetwarzanie procesu logowania

Jeśli w aplikacji masz już zaimplementowany proces logowania OpenID Connect, możesz użyć tokenu identyfikacyjnego bezpośrednio do uwierzytelniania w Firebase:

Kotlin

val providerId = "oidc.example-provider" // As registered in Firebase console.
val credential = oAuthCredential(providerId) {
    setIdToken(idToken) // ID token from OpenID Connect flow.
}
Firebase.auth
    .signInWithCredential(credential)
    .addOnSuccessListener { authResult ->
        // User is signed in.

        // IdP data available in:
        //    authResult.additionalUserInfo.profile
    }
    .addOnFailureListener { e ->
        // Handle failure.
    }

Java

AuthCredential credential = OAuthProvider
        .newCredentialBuilder("oidc.example-provider")  // As registered in Firebase console.
        .setIdToken(idToken)  // ID token from OpenID Connect flow.
        .build();
FirebaseAuth.getInstance()
        .signInWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // User is signed in.

                // IdP data available in:
                //    authResult.getAdditionalUserInfo().getProfile()
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Handle failure.
            }
        });

Dalsze kroki

Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone z danymi logowania, czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami dostawcy uwierzytelniania, za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane w projekcie Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie, niezależnie od tego, jak użytkownik się loguje.

  • W swoich aplikacjach możesz pobrać podstawowe informacje o profilu użytkownika z obiektu FirebaseUser. Zobacz sekcję Zarządzanie użytkownikami.

  • W regułach Firebase Realtime DatabaseCloud Storage Regułach bezpieczeństwa możesz pobrać z zmiennej auth unikalny identyfikator zalogowanego użytkownika i używać go do kontrolowania dostępu użytkownika do danych.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą danych uwierzytelniających od różnych dostawców, łącząc je z dotychczasowym kontem użytkownika.

Aby wylogować użytkownika, wywołaj funkcję signOut:

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();