Autenticar usuários com o Azure Active Directory B2C

Baixar exemplo Baixar o exemplo

O Azure Active Directory B2C fornece gerenciamento de identidade de nuvem para aplicativos web e móveis voltados para o consumidor. Este artigo mostra como usar o Azure Active Directory B2C para integrar o gerenciamento de identidade a um aplicativo móvel com a Biblioteca de Autenticação da Microsoft.

Visão geral

O ADB2C (Azure Active Directory B2C) é um serviço de gerenciamento de identidade para aplicativos voltados para o consumidor. Ele permite que os usuários entrem em seu aplicativo usando suas contas sociais existentes ou credenciais personalizadas, como email ou nome de usuário e senha. As contas de credencial personalizadas são conhecidas como contas locais .

O processo de integração do serviço de gerenciamento de identidade do Azure Active Directory B2C em um aplicativo móvel é o seguinte:

  1. Crie um locatário do Azure Active Directory B2C.
  2. Registre seu aplicativo móvel com o locatário do Azure Active Directory B2C.
  3. Crie políticas para inscrição e entrada e fluxos de usuário de senha esquecidos.
  4. Use a MSAL (Biblioteca de Autenticação da Microsoft) para iniciar um fluxo de trabalho de autenticação com seu locatário do Azure Active Directory B2C.

Observação

Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

O Azure Active Directory B2C dá suporte a vários provedores de identidade, incluindo Microsoft, GitHub, Facebook, Twitter e muito mais. Para obter mais informações sobre os recursos do Azure Active Directory B2C, consulte Documentação do Azure Active Directory B2C.

A Biblioteca de Autenticação da Microsoft dá suporte a várias arquiteturas e plataformas de aplicativos. Para obter informações sobre os recursos da MSAL, consulte Biblioteca de Autenticação da Microsoft no GitHub.

Configurar um locatário do Azure Active Directory B2C

Para executar o projeto de exemplo, você deve criar um locatário do Azure Active Directory B2C. Para obter mais informações, consulte Criar um locatário do Azure Active Directory B2C no portal do Azure.

Depois de criar um locatário, você precisará do nome do locatário e da ID do locatário para configurar o aplicativo móvel. A ID e o nome do locatário são definidos pelo domínio gerado quando você criou a URL do locatário. Se a URL do locatário gerada for https://contoso20190410tenant.onmicrosoft.com/ a ID do locatário e contoso20190410tenant.onmicrosoft.com o nome do locatário for contoso20190410tenant. Localize o domínio do locatário no portal do Azure clicando no diretório e no filtro de assinatura no menu superior. A captura de tela a seguir mostra o diretório do Azure e o botão de filtro de assinatura e o domínio do locatário:

Nome do locatário no diretório do Azure e na exibição de filtro de assinatura

No projeto de exemplo, edite o arquivo Constants.cs para definir os tenantName campos e tenantId . O código a seguir mostra como esses valores devem ser definidos se o domínio do locatário for https://contoso20190410tenant.onmicrosoft.com/, substitua esses valores por valores do portal:

public static class Constants
{
    static readonly string tenantName = "contoso20190410tenant";
    static readonly string tenantId = "contoso20190410tenant.onmicrosoft.com";
    ...
}

Registrar seu aplicativo móvel no Azure Active Directory B2C

Um aplicativo móvel deve ser registrado com o locatário antes que ele possa se conectar e autenticar usuários. O processo de registro atribui uma ID de Aplicativo exclusiva ao aplicativo e uma URL de Redirecionamento que direciona as respostas de volta para o aplicativo após a autenticação. Para obter mais informações, consulte Azure Active Directory B2C: Registrar seu aplicativo. Você precisará saber a ID do aplicativo atribuída ao aplicativo, que é listada após o nome do aplicativo na exibição de propriedades. A captura de tela a seguir mostra onde encontrar a ID do aplicativo:

ID do aplicativo na exibição de propriedades do aplicativo do Azure

A Biblioteca de Autenticação da Microsoft espera que a URL de Redirecionamento do aplicativo seja sua ID do Aplicativo prefixada com o texto "msal" e seguida por um ponto de extremidade chamado "autenticação". Se a ID do aplicativo for "1234abcd", a URL completa deverá ser msal1234abcd://auth. Verifique se o aplicativo habilitou a configuração de cliente nativo e crie um URI de Redirecionamento Personalizado usando sua ID do Aplicativo, conforme mostrado na captura de tela a seguir:

URI de redirecionamento personalizado na exibição de propriedades do aplicativo do Azure

A URL será usada posteriormente no AndroidApplicationManifest.xml e no iOS Info.plist.

No projeto de exemplo, edite o arquivo Constants.cs para definir o clientId campo como sua ID do Aplicativo. O código a seguir mostra como esse valor deve ser definido se a ID do aplicativo for 1234abcd:

public static class Constants
{
    static readonly string tenantName = "contoso20190410tenant";
    static readonly string tenantId = "contoso20190410tenant.onmicrosoft.com";
    static readonly string clientId = "1234abcd";
    ...
}

Criar políticas de inscrição e entrada e políticas de senha esquecidas

Uma política é uma experiência pela qual os usuários passam para concluir uma tarefa, como criar uma conta ou redefinir uma senha. Uma política também especifica o conteúdo dos tokens que o aplicativo recebe quando o usuário retorna da experiência. Você deve configurar políticas para inscrição e entrada da conta e redefinir senha. O Azure tem políticas internas que simplificam a criação de políticas comuns. Para obter mais informações, consulte Azure Active Directory B2C: Políticas internas.

Quando você concluir a configuração da política, deverá ter duas políticas na exibição Fluxos de usuário (políticas) no portal do Azure. A captura de tela a seguir demonstra duas políticas configuradas no portal do Azure:

Duas políticas configuradas na exibição Fluxos de usuário (políticas) do Azure

No projeto de exemplo, edite o arquivo Constants.cs para definir os policySignin campos e policyPassword para refletir os nomes escolhidos durante a configuração da política:

public static class Constants
{
    static readonly string tenantName = "contoso20190410tenant";
    static readonly string tenantId = "contoso20190410tenant.onmicrosoft.com";
    static readonly string clientId = "1234abcd";
    static readonly string policySignin = "B2C_1_signupsignin1";
    static readonly string policyPassword = "B2C_1_passwordreset";
    ...
}

Usar a MSAL (Biblioteca de Autenticação da Microsoft) para autenticação

O pacote NuGet da MSAL (Biblioteca de Autenticação da Microsoft) deve ser adicionado ao projeto compartilhado . NET Standard e aos projetos de plataforma em uma Xamarin.Forms solução. A MSAL inclui uma PublicClientApplicationBuilder classe que constrói um objeto que está aderindo à IPublicClientApplication interface. A MSAL utiliza cláusulas With para fornecer parâmetros adicionais aos métodos de construtor e autenticação.

No projeto de exemplo, o code behind para App.xaml define as propriedades estáticas denominadas AuthenticationClient e UIParente instancia o AuthenticationClient objeto no construtor. A WithIosKeychainSecurityGroup cláusula fornece um nome de grupo de segurança para aplicativos iOS. A WithB2CAuthority cláusula fornece a autoridade ou política padrão que será usada para autenticar usuários. A WithRedirectUri cláusula informa à instância dos Hubs de Notificação do Azure qual URI de redirecionamento usará se vários URIs forem especificados. O exemplo a seguir demonstra como instanciar o PublicClientApplication:

public partial class App : Application
{
    public static IPublicClientApplication AuthenticationClient { get; private set; }

    public static object UIParent { get; set; } = null;

    public App()
    {
        InitializeComponent();

        AuthenticationClient = PublicClientApplicationBuilder.Create(Constants.ClientId)
            .WithIosKeychainSecurityGroup(Constants.IosKeychainSecurityGroups)
            .WithB2CAuthority(Constants.AuthoritySignin)
            .WithRedirectUri($"msal{Constants.ClientId}://auth")
            .Build();

        MainPage = new NavigationPage(new LoginPage());
    }

    ...

Observação

Se a instância dos Hubs de Notificação do Azure tiver apenas um URI de redirecionamento definido, a AuthenticationClient instância poderá funcionar sem especificar o URI de Redirecionamento com a WithRedirectUri cláusula . No entanto, você sempre deve especificar esse valor caso sua configuração do Azure se expanda para dar suporte a outros clientes ou métodos de autenticação.

O OnAppearing manipulador de eventos no código LoginPage.xaml.cs por trás das chamadas AcquireTokenSilentAsync para atualizar o token de autenticação para usuários que fizeram logon antes. O processo de autenticação redireciona para o LogoutPage se tiver êxito e não faz nada em caso de falha. O exemplo a seguir mostra o processo de reautenticação silenciosa em OnAppearing:

public partial class LoginPage : ContentPage
{
    ...

    protected override async void OnAppearing()
    {
        try
        {
            // Look for existing account
            IEnumerable<IAccount> accounts = await App.AuthenticationClient.GetAccountsAsync();

            AuthenticationResult result = await App.AuthenticationClient
                .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
                .ExecuteAsync();

            await Navigation.PushAsync(new LogoutPage(result));
        }
        catch
        {
            // Do nothing - the user isn't logged in
        }
        base.OnAppearing();
    }

    ...
}

O OnLoginButtonClicked manipulador de eventos (acionado quando o botão Logon é clicado) chama AcquireTokenAsync. A biblioteca MSAL abre automaticamente o navegador do dispositivo móvel e navega até a página de logon. A URL de entrada, chamada autoridade, é uma combinação do nome do locatário e das políticas definidas no arquivo Constants.cs . Se o usuário escolher a opção de senha esquecida, ele será retornado ao aplicativo com uma exceção, que inicia a experiência de senha esquecida. O exemplo a seguir mostra o processo de autenticação:

public partial class LoginPage : ContentPage
{
    ...

    async void OnLoginButtonClicked(object sender, EventArgs e)
    {
        AuthenticationResult result;
        try
        {
            result = await App.AuthenticationClient
                .AcquireTokenInteractive(Constants.Scopes)
                .WithPrompt(Prompt.SelectAccount)
                .WithParentActivityOrWindow(App.UIParent)
                .ExecuteAsync();

            await Navigation.PushAsync(new LogoutPage(result));
        }
        catch (MsalException ex)
        {
            if (ex.Message != null && ex.Message.Contains("AADB2C90118"))
            {
                result = await OnForgotPassword();
                await Navigation.PushAsync(new LogoutPage(result));
            }
            else if (ex.ErrorCode != "authentication_canceled")
            {
                await DisplayAlert("An error has occurred", "Exception message: " + ex.Message, "Dismiss");
            }
        }
    }

    ...
}

O OnForgotPassword método é semelhante ao processo de entrada, mas implementa uma política personalizada. OnForgotPassword usa uma sobrecarga diferente de AcquireTokenAsync, que permite que você forneça uma Autoridade específica. O exemplo a seguir mostra como fornecer uma Autoridade personalizada ao adquirir um token:

public partial class LoginPage : ContentPage
{
    ...
    async Task<AuthenticationResult> OnForgotPassword()
    {
        try
        {
            return await App.AuthenticationClient
                .AcquireTokenInteractive(Constants.Scopes)
                .WithPrompt(Prompt.SelectAccount)
                .WithParentActivityOrWindow(App.UIParent)
                .WithB2CAuthority(Constants.AuthorityPasswordReset)
                .ExecuteAsync();
        }
        catch (MsalException)
        {
            // Do nothing - ErrorCode will be displayed in OnLoginButtonClicked
            return null;
        }
    }
}

A parte final da autenticação é o processo de saída. O OnLogoutButtonClicked método é chamado quando o usuário pressiona o botão de saída. Ele percorre todas as contas e garante que seus tokens tenham sido invalidados. O exemplo a seguir demonstra a implementação de saída:

public partial class LogoutPage : ContentPage
{
    ...
    async void OnLogoutButtonClicked(object sender, EventArgs e)
    {
        IEnumerable<IAccount> accounts = await App.AuthenticationClient.GetAccountsAsync();

        while (accounts.Any())
        {
            await App.AuthenticationClient.RemoveAsync(accounts.First());
            accounts = await App.AuthenticationClient.GetAccountsAsync();
        }

        await Navigation.PopAsync();
    }
}

iOS

No iOS, o esquema de URL personalizado que foi registrado no Azure Active Directory B2C deve ser registrado em Info.plist. A MSAL espera que o esquema de URL siga um padrão específico, descrito anteriormente em Registrar seu aplicativo móvel com o Azure Active Directory B2C. A captura de tela a seguir mostra o esquema de URL personalizado em Info.plist.

A MSAL também requer direitos de conjunto de chaves no iOS, registrados no Entitilements.plist, conforme mostrado na captura de tela a seguir:

Quando o Azure Active Directory B2C conclui a solicitação de autorização, ele redireciona para a URL de redirecionamento registrada. O esquema de URL personalizado resulta em iOS iniciando o aplicativo móvel e passando a URL como um parâmetro de inicialização, em que ele é processado pela OpenUrl substituição da classe do AppDelegate aplicativo e retorna o controle da experiência para a MSAL. A OpenUrl implementação é mostrada no exemplo de código a seguir:

using Microsoft.Identity.Client;

namespace TodoAzure.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        ...
        public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
        {
            AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
            return base.OpenUrl(app, url, options);
        }
    }
}

Android

No Android, o esquema de URL personalizado registrado no Azure Active Directory B2C deve ser registrado no AndroidManifest.xml. A MSAL espera que o esquema de URL siga um padrão específico, descrito anteriormente em Registrar seu aplicativo móvel com o Azure Active Directory B2C. O exemplo a seguir mostra o esquema de URL personalizado no AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.xamarin.adb2cauthorization">
  <uses-sdk android:minSdkVersion="15" />
  <application android:label="ADB2CAuthorization">
    <activity android:name="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" />
        <!-- example -->
        <!-- <data android:scheme="msalaaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" android:host="auth" /> -->
        <data android:scheme="INSERT_URI_SCHEME_HERE" android:host="auth" />
      </intent-filter>
    </activity>"
  </application>
</manifest>

A MainActivity classe deve ser modificada para fornecer o UIParent objeto ao aplicativo durante a OnCreate chamada. Quando o Azure Active Directory B2C conclui a solicitação de autorização, ele redireciona para o esquema de URL registrado do AndroidManifest.xml. O esquema de URI registrado resulta no Android chamando o OnActivityResult método com a URL como um parâmetro de inicialização, em que ele é processado pelo SetAuthenticationContinuationEventArgs método .

public class MainActivity : FormsAppCompatActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        Forms.Init(this, bundle);
        LoadApplication(new App());
        App.UIParent = this;
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
    }
}

Plataforma Universal do Windows

Nenhuma configuração adicional é necessária para usar a MSAL no Plataforma Universal do Windows

Executar o projeto

Execute o aplicativo em um dispositivo virtual ou físico. Tocar no botão Logon deve abrir o navegador e navegar até uma página em que você pode entrar ou criar uma conta. Depois de concluir o processo de entrada, você deverá ser retornado à página de logoff do aplicativo. A captura de tela a seguir mostra a tela de entrada do usuário em execução no Android e no iOS: