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

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

Zanim zaczniesz

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

  • Identyfikator klienta: ciąg znaków unikalny dla dostawcy, który identyfikuje Twoją aplikację. Dostawca może przypisać Ci inny identyfikator klienta dla każdej obsługiwanej platformy. Jest to jedna z wartości roszczenia aud w tokenach identyfikatora wydawanych przez dostawcę.

  • Tajny klucz klienta: tajny ciąg znaków, którego dostawca używa do potwierdzenia własności identyfikatora klienta. Każdy identyfikator klienta musi mieć odpowiadający mu tajny klucz klienta. (Ta wartość jest wymagana tylko wtedy, gdy używasz procesu kodu autoryzacji, co jest zdecydowanie zalecane).

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

Gdy uzyskasz powyższe informacje, włącz OpenID Connect jako dostawcę logowania w projekcie Firebase:

  1. Dodaj Firebase do projektu na Androida.

  2. Jeśli nie masz jeszcze wersji Firebase Authentication with Identity Platform, zaktualizuj ją. Uwierzytelnianie przy użyciu OpenID Connect jest dostępne tylko w zaktualizowanych projektach.

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

  4. Wybierz, czy będziesz używać przepływu kodu autoryzacji czy przepływu niejawnego.

    Jeśli Twój dostawca tożsamości obsługuje przepływ kodu, zawsze używaj tego przepływu. Przepływ niejawny jest mniej bezpieczny i zdecydowanie odradzamy jego używanie.

  5. Nadaj nazwę temu dostawcy. Zapisz wygenerowany identyfikator dostawcy, np. oidc.example-provider. Ten identyfikator będzie potrzebny podczas dodawania kodu logowania do aplikacji.

  6. Określ identyfikator klienta, tajny klucz klienta i ciąg wydawcy dostawcy. Wartości te muszą być dokładnie takie same jak wartości przypisane przez dostawcę.

  7. Zapisz zmiany.

Obsługa procesu logowania za pomocą pakietu Firebase SDK

Jeśli tworzysz aplikację na Androida, najłatwiejszym sposobem uwierzytelniania użytkowników w Firebase za pomocą dostawcy OIDC jest obsługa całego procesu logowania za pomocą 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ę OAuthProvider za pomocą jej 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 żądaniem 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ą OIDC, aby dowiedzieć się, jakie parametry są obsługiwane. Pamiętaj, że nie możesz przekazywać parametrów wymaganych przez Firebase za pomocą znaku setCustomParameters(). Są to parametry client_id, response_type, redirect_uri, state, scoperesponse_mode.

  3. Opcjonalnie: określ dodatkowe zakresy OAuth 2.0 poza podstawowym profilem, o które chcesz poprosić dostawcę 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);

    Aby dowiedzieć się, jakich zakresów używa dostawca OIDC, skontaktuj się z nim.

  4. Uwierzytelnij w Firebase za pomocą obiektu dostawcy OAuth. Pamiętaj, że w przeciwieństwie do 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 OnSuccessListenerOnFailureListener, które dołączasz, ponieważ zostaną one natychmiast odłączone, gdy operacja rozpocznie interfejs.

    Najpierw sprawdź, czy nie otrzymano już odpowiedzi. Logowanie tą metodą powoduje przeniesienie aktywności na drugi plan, co oznacza, że system może ją odzyskać podczas procesu logowania. Aby uniknąć sytuacji, w której użytkownik musi ponownie spróbować, sprawdź, czy wynik jest już dostępny.

    Aby sprawdzić, czy jest oczekiwany wynik, wywołaj funkcję 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, wywołaj funkcję 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 dotyczą przepływów logowania, ale możesz też połączyć dostawcę OIDC z istniejącym użytkownikiem za pomocą funkcji startActivityForLinkWithProvider. Możesz na przykład połączyć wielu dostawców z tym samym użytkownikiem, aby mógł on logować się 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. Ten sam wzorzec można zastosować w przypadku funkcji startActivityForReauthenticateWithProvider, która umożliwia pobieranie nowych danych logowania do operacji wymagających 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 obsługiwanie procesu logowania

Jeśli w aplikacji masz już zaimplementowany proces logowania przy użyciu OpenID Connect, możesz użyć tokena identyfikatora 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 o dostawcy uwierzytelniania, za pomocą których użytkownik się zalogował. Nowe konto jest przechowywane w projekcie w Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie, niezależnie od sposobu logowania.

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

  • W Firebase Realtime Database i Cloud Storage regułach bezpieczeństwa możesz pobrać unikalny identyfikator użytkownika zalogowanego ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą wielu dostawców uwierzytelniania, łącząc dane logowania dostawcy uwierzytelniania z istniejącym kontem użytkownika.

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

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();