Compartilhar via


Habilitar a autenticação em seu próprio aplicativo Android usando o Azure AD B2C

Este artigo mostra como adicionar a autenticação do Azure AD B2C (Azure Active Directory B2C) ao seu próprio aplicativo móvel do Android.

Use este artigo com Configurar a autenticação em um aplicativo Android de exemplo usando o Azure AD B2C, substituindo o aplicativo Android de exemplo por seu próprio. Depois de concluir as instruções deste artigo, seu aplicativo aceitará os logins por meio Azure AD B2C.

Pré-requisitos

Examine os pré-requisitos e as instruções de integração em Configurar a autenticação em um aplicativo Android de exemplo usando o Azure AD B2C.

Criar um projeto de aplicativo Android

Se você ainda não tiver um aplicativo Android, configure um novo projeto da seguinte maneira:

  1. No Android Studio, selecione Iniciar um novo projeto do Android Studio.
  2. Selecione Atividade Básica e Avançar.
  3. Nome do seu aplicativo.
  4. Guarde o nome do pacote. Você o inserirá depois no portal do Azure.
  5. Altere a linguagem de Kotlin para Java.
  6. Defina o Nível mínimo da API como API 19 ou superior e selecione Concluir.
  7. Na exibição do projeto, escolha Projeto na lista suspensa para exibir os arquivos do projeto que são e que não são de origem, abra app/build.gradle e defina targetSdkVersion como 28.

Etapa 1: Instalar as dependências

Na janela do projeto do Android Studio, navegue até aplicativo>build.gradle e adicione o seguinte:

apply plugin: 'com.android.application'

allprojects {
    repositories {
    mavenCentral()
    google()
    mavenLocal()
    maven {
        url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
    }
    maven {
        name "vsts-maven-adal-android"
        url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
        credentials {
            username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
            password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
        }
    }
    jcenter()
    }
}
dependencies{
    implementation 'com.microsoft.identity.client:msal:2.+'
    }
packagingOptions{
    exclude("META-INF/jersey-module-version")
}

Etapa 2: Adicionar os componentes de autenticação

O código de exemplo é composto pelos componentes a seguir. Adicione esses componentes do aplicativo Android de exemplo ao seu próprio aplicativo.

Componente Tipo Fonte Descrição
B2CUser Classe Kotlin Java Representa um usuário B2C. Essa classe permite que os usuários se inscrevam com várias políticas.
B2CModeFragment Classe de fragmento Kotlin Java Um fragmento representa uma parte modular da credencial com a interface do usuário do Azure AD B2C dentro de sua atividade principal. Esse fragmento contém a maior parte do código de autenticação.
fragment_b2c_mode.xml Layout do fragmento Kotlin Java Define a estrutura da interface do usuário para o componente de fragmento B2CModeFragment.
B2CConfiguration Classe Kotlin Java Esse arquivo de configuração contém informações sobre seu provedor de identidade do Azure AD B2C. O aplicativo móvel usa essas informações para estabelecer uma relação de confiança com o Azure AD B2C, conectar e desconectar usuários, adquirir tokens e validá-los. Para obter mais definições de configuração, confira o arquivo auth_config_b2c.json.
auth_config_b2c.json Arquivo JSON Kotlin Java Esse arquivo de configuração contém informações sobre seu provedor de identidade do Azure AD B2C. O aplicativo móvel usa essas informações para estabelecer uma relação de confiança com o Azure AD B2C, conectar e desconectar usuários, adquirir tokens e validá-los. Para obter mais definições de configuração, confira a classe B2CConfiguration.

Etapa 3: Configurar seu aplicativo Android

Depois de adicionar os componentes de autenticação, configure seu aplicativo Android com as configurações do Azure AD B2C. As configurações do provedor de identidade do Azure AD B2C são definidas no arquivo auth_config_b2c.json e na classe B2CConfiguration.

Para ver as diretrizes, consulte Configurar um aplicativo móvel de exemplo.

Etapa 4: Definir o URI de redirecionamento

Configure onde o seu aplicativo escuta a resposta do token do Azure AD B2C.

  1. Gere um novo hash de assinatura de desenvolvimento. Isso mudará para cada ambiente de desenvolvimento.

    Para Windows:

    keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
    

    Para iOS:

    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
    

    Para um ambiente de produção, use o seguinte comando:

    keytool -exportcert -alias SIGNATURE_ALIAS -keystore PATH_TO_KEYSTORE | openssl sha1 -binary | openssl base64
    

    Se precisar de ajuda para assinar seus aplicativos, confira Assinar seu aplicativo Android.

  2. Selecione aplicativo>src>principal>AndroidManifest.xml e adicione a seguinte atividade BrowserTabActivity ao corpo do aplicativo:

    <!--Intent filter to capture System Browser or Authenticator calling back to our app after sign-in-->
    <activity
        android:name="com.microsoft.identity.client.BrowserTabActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="msauth"
                android:host="Package_Name"
                android:path="/Signature_Hash" />
        </intent-filter>
    </activity>
    
  3. Substitua Signature_Hash pela hash que você gerou.

  4. Substitua Package_Name pelo nome do pacote Android.

Para atualizar o registro do aplicativo móvel com o URI de redirecionamento de aplicativo, faça o seguinte:

  1. Entre no portal do Azure.
  2. Se você tiver acesso a vários locatários, selecione o ícone Configurações no menu superior para alternar para o seu locatário do Azure Active Directory B2C no menu Diretórios + assinaturas.
  3. Pesquise e selecione Azure AD B2C.
  4. Selecione Registros de aplicativo e, em seguida, selecione o aplicativo em que você se registrou na Etapa 2.3: Registrar o aplicativo móvel.
  5. Selecione Autenticação.
  6. Em Android, selecione Adicionar URI.
  7. Insira o Nome do pacote e o Hash de assinatura.
  8. Selecione Salvar.

O URI de redirecionamento e a atividade BrowserTabActivity devem estar semelhantes ao seguinte exemplo:

A URL de redirecionamento para o Android de exemplo tem esta aparência:

msauth://com.azuresamples.msalandroidkotlinapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D

O filtro de intenção usa o mesmo padrão, conforme mostrado no snippet XML a seguir:

<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.azuresamples.msalandroidkotlinapp"
            android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY="
            android:scheme="msauth" />
    </intent-filter>
</activity>

Etapa 5: Personalizar seus blocos de construção de código

Esta seção descreve os blocos de construção de código que habilitam a autenticação para o aplicativo Android. A tabela a seguir lista os métodos B2CModeFragment e a forma de personalizar o código.

Etapa 5.1: Criar uma instância de um aplicativo cliente público

Os aplicativos cliente públicos não são confiáveis para manter os segredos do aplicativo com segurança, além de não terem segredos do cliente. Em onCreate ou onCreateView crie uma instância do MSAL usando o objeto de aplicativo cliente público de várias contas.

A classe MultipleAccountPublicClientApplication é usada para criar aplicativos baseados em MSAL que permitem que várias contas sejam assinadas ao mesmo tempo. A classe permite entrar com vários fluxos de usuário ou políticas personalizadas do Azure AD B2C. Por exemplo, o usuário entra com um fluxo de usuário de inscrição ou acesso e, posteriormente, executa um fluxo de usuário de edição de perfil.

O trecho de código a seguir demonstra como iniciar a biblioteca MSAL com o arquivo JSON de configuração auth_config_b2c.json.

PublicClientApplication.createMultipleAccountPublicClientApplication(context!!,
    R.raw.auth_config_b2c,
    object : IMultipleAccountApplicationCreatedListener {
        override fun onCreated(application: IMultipleAccountPublicClientApplication) {
            // Set the MultipleAccountPublicClientApplication to the class member b2cApp
            b2cApp = application
            // Load the account (if there is any)
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            // Error handling
            displayError(exception)
        }
    })

Etapa 5.2: Carregar contas

Quando o aplicativo vem para o primeiro plano, carrega a conta existente para determinar se os usuários estão conectados. Use esse método para atualizar a interface do usuário com o estado de autenticação. Por exemplo, você pode habilitar ou desabilitar o botão de saída.

O trecho de código a seguir demonstra como carregar as contas.

private fun loadAccounts() {
    if (b2cApp == null) {
        return
    }
    b2cApp!!.getAccounts(object : LoadAccountsCallback {
        override fun onTaskCompleted(result: List<IAccount>) {
            users = B2CUser.getB2CUsersFromAccountList(result)
            updateUI(users)
        }
    
        override fun onError(exception: MsalException) {
            displayError(exception)
        }
    })
    }

Etapa 5.3: Iniciar uma solicitação de autorização interativa

Uma solicitação de autorização interativa é um fluxo em que os usuários são solicitados a se inscreverem ou entrarem. O método initializeUI configura o evento de clique runUserFlowButton. Quando o usuário seleciona o botão Executar fluxo de usuário, o aplicativo leva-o ao Azure AD B2C para concluir o fluxo de entrada.

O método runUserFlowButton.setOnClickListener prepara o objeto AcquireTokenParameters com os dados relevantes da solicitação de autorização. O método acquireToken solicita que o usuário conclua o fluxo de inscrição ou acesso.

O trecho de código a seguir demonstra como iniciar a solicitação de autorização interativa:

val parameters = AcquireTokenParameters.Builder()
        .startAuthorizationFromActivity(activity)
        .fromAuthority(getAuthorityFromPolicyName(policy_list.getSelectedItem().toString()))
        .withScopes(B2CConfiguration.scopes)
        .withPrompt(Prompt.LOGIN)
        .withCallback(authInteractiveCallback)
        .build()

b2cApp!!.acquireToken(parameters)

Etapa 5.4: Fazer um retorno de chamada de solicitação de autorização interativa

Depois que o usuário concluir o fluxo de autorização com ou sem êxito, o resultado será retornado para o método de retorno de chamada getAuthInteractiveCallback().

O método de retorno de chamada passa ao objeto AuthenticationResult ou uma mensagem de erro no objeto MsalException. Use este método para:

  • Atualizar a interface do usuário do aplicativo móvel com informações após a finalização da login
  • Recarregar o objeto de contas
  • Chamar um serviço de API Web com um token de acesso.
  • Tratar os erros de autenticação

O trecho de código a seguir demonstra o uso do retorno de chamada de autenticação interativa.

private val authInteractiveCallback: AuthenticationCallback
    private get() = object : AuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            /* Successfully got a token, use it to call a protected resource; web API  */
            Log.d(TAG, "Successfully authenticated")

            /* display result info */
            displayResult(authenticationResult)

            /* Reload account asynchronously to get the up-to-date list. */
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            val B2C_PASSWORD_CHANGE = "AADB2C90118"
            if (exception.message!!.contains(B2C_PASSWORD_CHANGE)) {
                txt_log!!.text = """
                    Users click the 'Forgot Password' link in a sign-up or sign-in user flow.
                    Your application needs to handle this error code by running a specific user flow that resets the password.
                    """.trimIndent()
                return
            }

            /* Failed to acquireToken */Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            }
        }

        override fun onCancel() {
            /* User canceled the authentication */
            Log.d(TAG, "User cancelled login.")
        }
    }

Etapa 6: Chamar uma API Web

Para chamar uma API Web de autorização baseada em token, o aplicativo precisa ter um token de acesso válido. O aplicativo faz as seguintes ações:

  1. Adquire um token de acesso com as permissões necessárias (escopos) para o ponto de extremidade da API Web.
  2. Passa o token de acesso como um token de portador no cabeçalho de autorização da solicitação HTTP usando este formato:
Authorization: Bearer <access-token>

Quando os usuários fazem login interativamente, o aplicativo obtém um token de acesso no método de retorno de chamada getAuthInteractiveCallback. Para chamadas de API Web consecutivas, use o procedimento silencioso de aquisição de token, conforme descrito nesta seção.

Antes de chamar uma API Web, chame o método acquireTokenSilentAsync com os escopos apropriados para o seu ponto de extremidade da API Web. A biblioteca MSAL faz o seguinte:

  1. Tenta buscar um token de acesso com os escopos solicitados do cache de token. Se o token estiver presente, o token será retornado.
  2. Se o token não estiver presente no cache de token, o MSAL tentará usar seu token de atualização para adquirir um novo token.
  3. Se o token de atualização não existir ou tiver expirado, será retornada uma exceção. Recomendamos solicitar que o usuário entre de forma interativa.

O seguinte trecho de código demonstra como adquirir um token de acesso:

O evento de clique do botão acquireTokenSilentButton adquire um token de acesso com os escopos fornecidos.

btn_acquireTokenSilently.setOnClickListener(View.OnClickListener {
    if (b2cApp == null) {
        return@OnClickListener
    }
    val selectedUser = users!![user_list.getSelectedItemPosition()]
    selectedUser.acquireTokenSilentAsync(b2cApp!!,
            policy_list.getSelectedItem().toString(),
            B2CConfiguration.scopes,
            authSilentCallback)
})

O método de retorno de chamada authSilentCallback retorna um token de acesso e chama uma API da Web:

private val authSilentCallback: SilentAuthenticationCallback
    private get() = object : SilentAuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            Log.d(TAG, "Successfully authenticated")

            /* Call your web API here*/
            callWebAPI(authenticationResult)
        }

        override fun onError(exception: MsalException) {
            /* Failed to acquireToken */
            Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            } else if (exception is MsalUiRequiredException) {
                /* Tokens expired or no session, retry with interactive */
            }
        }
    }

O exemplo a seguir demonstra como chamar uma API Web protegida com um token de portador:

@Throws(java.lang.Exception::class)
private fun callWebAPI(authenticationResult: IAuthenticationResult) {
    val accessToken = authenticationResult.accessToken
    val thread = Thread {
        try {
            val url = URL("https://your-app-service.azurewebsites.net/helo")
            val conn = url.openConnection() as HttpsURLConnection
            conn.setRequestProperty("Accept", "application/json")
            
            // Set the bearer token
            conn.setRequestProperty("Authorization", "Bearer $accessToken")
            if (conn.responseCode == HttpURLConnection.HTTP_OK) {
                val br = BufferedReader(InputStreamReader(conn.inputStream))
                var strCurrentLine: String?
                while (br.readLine().also { strCurrentLine = it } != null) {
                    Log.d(TAG, strCurrentLine)
                }
            }
            conn.disconnect()
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    thread.start()
}

Adicionar permissão para executar operações de rede

Para executar operações de rede no seu aplicativo, adicione a permissão a seguir ao manifesto. Para saber mais, confira Conectar à rede.

<uses-permission android:name="android.permission.INTERNET"/>

Próximas etapas

Saiba como: