Uwierzytelnij się za pomocą OpenID Connect na Androidzie

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

Zanim zaczniesz

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

  • Identyfikator klienta : ciąg unikalny dla dostawcy, który identyfikuje Twoją aplikację. Twój dostawca może przypisać Ci inny identyfikator klienta dla każdej obsługiwanej platformy. Jest to jedna z wartości żądania aud w tokenach identyfikacyjnych wystawionych przez Twojego dostawcę.

  • Sekret klienta : Tajny ciąg używany przez dostawcę do potwierdzenia własności identyfikatora klienta. Dla każdego identyfikatora klienta potrzebny będzie pasujący klucz tajny klienta. (Ta wartość jest wymagana tylko wtedy, gdy używasz przepływu kodu autoryzacji , co jest zdecydowanie zalecane).

  • Issuer : ciąg znaków, który identyfikuje dostawcę. Ta wartość musi być adresem URL, który po dołączeniu z /.well-known/openid-configuration oznacza lokalizację dokumentu wykrywania OIDC dostawcy. Na przykład jeśli wystawcą jest https://auth.example.com , dokument odnajdywania musi być dostępny pod https://auth.example.com/.well-known/openid-configuration .

Po uzyskaniu powyższych informacji włącz OpenID Connect jako dostawcę logowania dla swojego projektu Firebase:

  1. Dodaj Firebase do swojego projektu na Androida .

  2. Jeśli nie dokonałeś uaktualnienia do Firebase Authentication with Identity Platform, zrób to. Uwierzytelnianie OpenID Connect jest dostępne tylko w zaktualizowanych projektach.

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

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

    Powinieneś zawsze używać przepływu kodu, jeśli twój dostawca go obsługuje . Przepływ niejawny jest mniej bezpieczny i zdecydowanie odradza się jego używanie.

  5. Podaj nazwę tego dostawcy. Zanotuj wygenerowany identyfikator dostawcy: na przykład oidc.example-provider . Będziesz potrzebować tego identyfikatora, gdy dodasz kod logowania do swojej aplikacji.

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

  7. Zapisz zmiany.

Obsługuj proces logowania za pomocą Firebase SDK

Jeśli tworzysz aplikację na Androida, najłatwiejszym sposobem uwierzytelnienia użytkowników w Firebase przy użyciu dostawcy OIDC jest obsłużenie całego procesu logowania za pomocą Firebase Android SDK.

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

  1. Skonstruuj instancję dostawcy OAuthProvider przy użyciu jego konstruktora z identyfikatorem dostawcy

    Kotlin+KTX

    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+KTX

    // 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");

    Sprawdź u swojego dostawcy OIDC, jakie parametry obsługuje. Pamiętaj, że nie możesz przekazać parametrów wymaganych przez Firebase za pomocą setCustomParameters() . Te parametry to client_id , response_type , redirect_uri , state , scope i response_mode .

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

    Kotlin+KTX

    // 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 uzyskać informacje o używanych przez niego zakresach.

  4. Uwierzytelnij się w Firebase przy użyciu obiektu dostawcy OAuth. Pamiętaj, że w przeciwieństwie do innych operacji FirebaseAuth przejmie to kontrolę nad interfejsem użytkownika, wyświetlając niestandardową kartę Chrome . W rezultacie nie odwołuj się do swojej aktywności w dołączonych OnSuccessListener i OnFailureListener , ponieważ zostaną one natychmiast odłączone, gdy operacja uruchomi interfejs użytkownika.

    Najpierw sprawdź, czy otrzymałeś już odpowiedź. Zalogowanie się przy użyciu tej metody powoduje, że Twoja aktywność działa w tle, co oznacza, że ​​może zostać odzyskana przez system podczas procesu logowania. Aby upewnić się, że użytkownik nie spróbuje ponownie, jeśli tak się stanie, powinieneś sprawdzić, czy wynik już istnieje.

    Aby sprawdzić, czy istnieje oczekujący wynik, wywołaj getPendingAuthResult :

    Kotlin+KTX

    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 startActivityForSignInWithProvider :

    Kotlin+KTX

    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. Chociaż powyższe przykłady koncentrują się na przepływach logowania, masz również możliwość połączenia dostawcy OIDC z istniejącym użytkownikiem przy użyciu startActivityForLinkWithProvider . Na przykład możesz połączyć wielu dostawców z tym samym użytkownikiem, umożliwiając im logowanie się za pomocą jednego z nich.

    Kotlin+KTX

    // 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 wzorca można użyć z startActivityForReauthenticateWithProvider , którego można użyć do pobrania świeżych poświadczeń dla poufnych operacji wymagających niedawnego logowania.

    Kotlin+KTX

    // 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ęcznie obsługuj przepływ logowania

Jeśli w swojej aplikacji zaimplementowałeś już proces logowania OpenID Connect, możesz użyć tokena ID bezpośrednio do uwierzytelnienia w Firebase:

Kotlin+KTX

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.
            }
        });

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania — za pomocą których użytkownik się logował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikacji użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, jak użytkownik się loguje.

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

  • W regułach bezpieczeństwa Firebase Realtime Database i Cloud Storage możesz uzyskać unikalny identyfikator zalogowanego użytkownika 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ę do Twojej aplikacji przy użyciu wielu dostawców uwierzytelniania, łącząc poświadczenia dostawcy uwierzytelniania z istniejącym kontem użytkownika.

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

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();