Autenticar usando OpenID Connect no Android

Se você tiver atualizado para o Firebase Authentication com Identity Platform, poderá autenticar seus usuários com o Firebase usando o provedor compatível com OpenID Connect (OIDC) de sua preferência. Isso possibilita o uso de provedores de identidade não suportados nativamente pelo Firebase.

Antes de você começar

Para conectar usuários usando um provedor OIDC, primeiro você deve coletar algumas informações do provedor:

  • ID do cliente : uma string exclusiva do provedor que identifica seu aplicativo. Seu provedor pode atribuir a você um ID de cliente diferente para cada plataforma que você oferece suporte. Este é um dos valores da declaração aud em tokens de identificação emitidos pelo seu provedor.

  • Segredo do cliente : uma sequência secreta que o provedor usa para confirmar a propriedade de um ID do cliente. Para cada ID de cliente, você precisará de um segredo de cliente correspondente. (Esse valor será obrigatório somente se você estiver usando o fluxo de código de autenticação , o que é altamente recomendado.)

  • Emissor : uma string que identifica seu provedor. Esse valor deve ser uma URL que, quando anexada a /.well-known/openid-configuration , seja o local do documento de descoberta OIDC do provedor. Por exemplo, se o emissor for https://auth.example.com , o documento de descoberta deverá estar disponível em https://auth.example.com/.well-known/openid-configuration .

Depois de obter as informações acima, ative o OpenID Connect como provedor de login para seu projeto do Firebase:

  1. Adicione o Firebase ao seu projeto Android .

  2. Se você ainda não atualizou para o Firebase Authentication com Identity Platform, faça-o. A autenticação OpenID Connect está disponível apenas em projetos atualizados.

  3. Na página Provedores de login do Firebase Console, clique em Adicionar novo provedor e em OpenID Connect .

  4. Selecione se você usará o fluxo de código de autorização ou o fluxo de concessão implícita .

    Você deve usar sempre o fluxo de código se o seu provedor oferecer suporte . O fluxo implícito é menos seguro e seu uso é fortemente desencorajado.

  5. Dê um nome a este provedor. Observe o ID do provedor gerado: algo como oidc.example-provider . Você precisará desse ID ao adicionar o código de login ao seu aplicativo.

  6. Especifique o ID do cliente e o segredo do cliente, além da string do emissor do seu provedor. Esses valores devem corresponder exatamente aos valores que seu provedor atribuiu a você.

  7. Salve suas alterações.

Lidar com o fluxo de login com o SDK do Firebase

Se você estiver criando um aplicativo Android, a maneira mais fácil de autenticar seus usuários com o Firebase usando seu provedor OIDC é lidar com todo o fluxo de login com o Firebase Android SDK.

Para lidar com o fluxo de login com o Firebase Android SDK, siga estas etapas:

  1. Construa uma instância de um OAuthProvider usando seu Builder com o ID do provedor

    Kotlin+KTX

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

    Java

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

  2. Opcional : Especifique parâmetros OAuth customizados adicionais que você deseja enviar com a solicitação 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");

    Verifique com seu provedor OIDC os parâmetros que eles suportam. Observe que você não pode passar parâmetros exigidos pelo Firebase com setCustomParameters() . Esses parâmetros são client_id , Response_Type , Redirect_uri , State , Scope e Response_mode .

  3. Opcional : Especifique escopos adicionais do OAuth 2.0 além do perfil básico que você deseja solicitar do provedor de autenticação.

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

    Verifique com seu provedor OIDC os escopos que eles usam.

  4. Autentique-se com o Firebase usando o objeto do provedor OAuth. Observe que, diferentemente de outras operações do FirebaseAuth, isso assumirá o controle da sua IU abrindo uma guia personalizada do Chrome . Como resultado, não faça referência à sua atividade no OnSuccessListener e OnFailureListener anexados, pois eles serão desconectados imediatamente quando a operação iniciar a interface do usuário.

    Você deve primeiro verificar se já recebeu uma resposta. O login com esse método coloca sua atividade em segundo plano, o que significa que ela pode ser recuperada pelo sistema durante o fluxo de login. Para ter certeza de que o usuário não tentará novamente se isso acontecer, você deve verificar se um resultado já está presente.

    Para verificar se há um resultado pendente, chame 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.
    }

    Para iniciar o fluxo de login, chame 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. Embora os exemplos acima se concentrem em fluxos de entrada, você também tem a capacidade de vincular um provedor OIDC a um usuário existente usando startActivityForLinkWithProvider . Por exemplo, você pode vincular vários provedores ao mesmo usuário, permitindo que eles façam login com qualquer um deles.

    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. O mesmo padrão pode ser usado com startActivityForReauthenticateWithProvider , que pode ser usado para recuperar credenciais novas para operações confidenciais que exigem login recente.

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

Lidar com o fluxo de login manualmente

Se você já implementou o fluxo de login do OpenID Connect no seu aplicativo, poderá usar o token de ID diretamente para autenticar no 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.
            }
        });

Próximos passos

Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais (ou seja, nome de usuário e senha, número de telefone ou informações do provedor de autenticação) com as quais o usuário fez login. Essa nova conta é armazenada como parte do seu projeto do Firebase e pode ser usada para identificar um usuário em todos os aplicativos do seu projeto, independentemente de como o usuário faz login.

  • Nos seus aplicativos, você pode obter informações básicas do perfil do usuário no objeto FirebaseUser . Consulte Gerenciar usuários .

  • Nas regras de segurança do Firebase Realtime Database e do Cloud Storage , você pode obter o ID de usuário exclusivo do usuário conectado na variável auth e usá-lo para controlar quais dados um usuário pode acessar.

Você pode permitir que os usuários façam login no seu aplicativo usando vários provedores de autenticação vinculando as credenciais do provedor de autenticação a uma conta de usuário existente.

Para desconectar um usuário, chame signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();