Autenticación de usuarios con Azure Active Directory B2C

Descargar ejemploDescargar el ejemplo

Azure Active Directory B2C proporciona administración de identidades en la nube para aplicaciones web y móviles orientadas al consumidor. En este artículo se muestra cómo usar Azure Active Directory B2C para integrar la administración de identidades en una aplicación móvil con la biblioteca de autenticación de Microsoft.

Información general

Azure Active Directory B2C (ADB2C) es un servicio de administración de identidades para aplicaciones orientadas al consumidor. Permite a los usuarios iniciar sesión en la aplicación con sus cuentas sociales existentes o credenciales personalizadas, como el correo electrónico o el nombre de usuario y la contraseña. Las cuentas de credenciales personalizadas se conocen como cuentas locales .

El proceso para integrar el servicio de administración de identidades de Azure Active Directory B2C en una aplicación móvil es el siguiente:

  1. Crear un inquilino de Azure Active Directory B2C.
  2. Registre la aplicación móvil con el inquilino de Azure Active Directory B2C.
  3. Cree directivas para el registro y el inicio de sesión, y olvidó los flujos de usuario de contraseña.
  4. Use la Biblioteca de autenticación de Microsoft (MSAL) para iniciar un flujo de trabajo de autenticación con el inquilino de Azure Active Directory B2C.

Nota

Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

Azure Active Directory B2C admite varios proveedores de identidades, como Microsoft, GitHub, Facebook, Twitter y mucho más. Para más información sobre las funcionalidades de Azure Active Directory B2C, consulte la documentación de Azure Active Directory B2C.

La Biblioteca de autenticación de Microsoft admite varias plataformas y arquitecturas de aplicaciones. Para obtener información sobre las funcionalidades de MSAL, consulte Biblioteca de autenticación de Microsoft en GitHub.

Configuración de un inquilino de Azure Active Directory B2C

Para ejecutar el proyecto de ejemplo, debe crear un inquilino de Azure Active Directory B2C. Para más información, consulte Creación de un inquilino de Azure Active Directory B2C en el Azure Portal.

Una vez creado un inquilino, necesitará el nombre del inquilino y el identificador de inquilino para configurar la aplicación móvil. El identificador de inquilino y el nombre se definen mediante el dominio generado al crear la dirección URL del inquilino. Si la dirección URL de inquilino generada es https://contoso20190410tenant.onmicrosoft.com/ el identificador de inquilino y contoso20190410tenant.onmicrosoft.com el nombre del inquilino es contoso20190410tenant. Busque el dominio de inquilino en el Azure Portal haciendo clic en el filtro de directorio y suscripción en el menú superior. En la captura de pantalla siguiente se muestra el botón de filtro de directorio y suscripción de Azure y el dominio del inquilino:

Nombre del inquilino en la vista de filtro de suscripción y directorio de Azure

En el proyecto de ejemplo, edite el archivo Constants.cs para establecer los tenantName campos y tenantId . En el código siguiente se muestra cómo se deben establecer estos valores si el dominio del inquilino es https://contoso20190410tenant.onmicrosoft.com/, reemplace estos valores por valores del portal:

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

Registro de la aplicación móvil con Azure Active Directory B2C

Una aplicación móvil debe registrarse con el inquilino para poder conectarse y autenticar a los usuarios. El proceso de registro asigna un identificador de aplicación único a la aplicación y una dirección URL de redireccionamiento que dirige las respuestas a la aplicación después de la autenticación. Para más información, consulte Azure Active Directory B2C: Registro de la aplicación. Deberá conocer el identificador de aplicación asignado a la aplicación, que aparece después del nombre de la aplicación en la vista de propiedades. En la captura de pantalla siguiente se muestra dónde encontrar el identificador de aplicación:

Identificador de aplicación en la vista de propiedades de la aplicación de Azure

La biblioteca de autenticación de Microsoft espera que la dirección URL de redirección de la aplicación tenga el prefijo id. de aplicación con el texto "msal" y seguido de un punto de conexión denominado "auth". Si el identificador de la aplicación es "1234abcd", la dirección URL completa debe ser msal1234abcd://auth. Asegúrese de que la aplicación ha habilitado la configuración de Native Client y cree un URI de redirección personalizado mediante el identificador de aplicación, como se muestra en la captura de pantalla siguiente:

URI de redirección personalizado en la vista de propiedades de la aplicación de Azure

La dirección URL se usará más adelante en el ApplicationManifest.xml de Android y en el archivo Info.plist de iOS.

En el proyecto de ejemplo, edite el archivo Constants.cs para establecer el campo en el clientIdidentificador de aplicación. En el código siguiente se muestra cómo se debe establecer este valor si el identificador de aplicación es 1234abcd:

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

Creación de directivas de registro e inicio de sesión, y directivas de contraseña olvidada

Una directiva es una experiencia que los usuarios pasan para completar una tarea como crear una cuenta o restablecer una contraseña. Una directiva también especifica el contenido de los tokens que recibe la aplicación cuando el usuario vuelve de la experiencia. Debe configurar directivas para el registro y el inicio de sesión de la cuenta, y restablecer la contraseña. Azure tiene directivas integradas que simplifican la creación de directivas comunes. Para más información, consulte Azure Active Directory B2C: Directivas integradas.

Cuando haya completado la configuración de directivas, debe tener dos directivas en la vista Flujos de usuario (directivas) de la Azure Portal. En la captura de pantalla siguiente se muestran dos directivas configuradas en el Azure Portal:

Dos directivas configuradas en la vista Flujos de usuario (directivas) de Azure

En el proyecto de ejemplo, edite el archivo Constants.cs para establecer los policySignin campos y policyPassword para reflejar los nombres que eligió durante la configuración de la directiva:

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 la Biblioteca de autenticación de Microsoft (MSAL) para la autenticación

El paquete NuGet de la Biblioteca de autenticación de Microsoft (MSAL) debe agregarse al proyecto compartido, .NET Standard y a los proyectos de plataforma de una Xamarin.Forms solución. MSAL incluye una PublicClientApplicationBuilder clase que construye un objeto que se adhiere a la IPublicClientApplication interfaz . MSAL utiliza cláusulas With para proporcionar parámetros adicionales al constructor y los métodos de autenticación.

En el proyecto de ejemplo, el código subyacente para App.xaml define las propiedades estáticas denominadas AuthenticationClient y UIParent, y crea una instancia del AuthenticationClient objeto en el constructor. La WithIosKeychainSecurityGroup cláusula proporciona un nombre de grupo de seguridad para aplicaciones iOS. La WithB2CAuthority cláusula proporciona la directiva o autoridad predeterminada que se usará para autenticar a los usuarios. La WithRedirectUri cláusula indica a la instancia de Azure Notification Hubs qué URI de redirección se usará si se especifican varios URI. En el ejemplo siguiente se muestra cómo crear una instancia de :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());
    }

    ...

Nota

Si la instancia de Azure Notification Hubs solo tiene definido un URI de redirección, la AuthenticationClient instancia puede funcionar sin especificar el URI de redirección con la WithRedirectUri cláusula . Sin embargo, siempre debe especificar este valor en caso de que la configuración de Azure se expanda para admitir otros clientes o métodos de autenticación.

El OnAppearing controlador de eventos del código LoginPage.xaml.cs subyacente llama AcquireTokenSilentAsync a para actualizar el token de autenticación de los usuarios que han iniciado sesión antes. El proceso de autenticación redirige a LogoutPage si se ejecuta correctamente y no hace nada en caso de error. En el ejemplo siguiente se muestra el proceso de reautenticación silenciosa en 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();
    }

    ...
}

El OnLoginButtonClicked controlador de eventos (desencadenado cuando se hace clic en el botón Inicio de sesión) llama a AcquireTokenAsync. La biblioteca MSAL abre automáticamente el explorador de dispositivos móviles y navega a la página de inicio de sesión. La dirección URL de inicio de sesión, denominada Autoridad, es una combinación del nombre del inquilino y las directivas definidas en el archivo Constants.cs . Si el usuario elige la opción de contraseña olvidada, se devuelve a la aplicación con una excepción, que inicia la experiencia de contraseña olvidada. En el ejemplo siguiente se muestra el proceso de autenticación:

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

    ...
}

El OnForgotPassword método es similar al proceso de inicio de sesión, pero implementa una directiva personalizada. OnForgotPassword usa una sobrecarga diferente de AcquireTokenAsync, que permite proporcionar una autoridad específica. En el ejemplo siguiente se muestra cómo proporcionar una entidad personalizada al adquirir un 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;
        }
    }
}

La última parte de la autenticación es el proceso de cierre de sesión. Se OnLogoutButtonClicked llama al método cuando el usuario presiona el botón cerrar sesión. Recorre en bucle todas las cuentas y garantiza que sus tokens se han invalidado. En el ejemplo siguiente se muestra la implementación de cierre de sesión:

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

En iOS, el esquema de dirección URL personalizado que se registró con Azure Active Directory B2C debe registrarse en Info.plist. MSAL espera que el esquema de dirección URL se ajuste a un patrón específico, descrito anteriormente en Registro de la aplicación móvil con Azure Active Directory B2C. En la captura de pantalla siguiente se muestra el esquema de dirección URL personalizado en Info.plist.

MSAL también requiere derechos de cadena de claves en iOS, registrados en Entitilements.plist, como se muestra en la captura de pantalla siguiente:

Cuando Azure Active Directory B2C completa la solicitud de autorización, se redirige a la dirección URL de redireccionamiento registrada. El esquema de dirección URL personalizada da como resultado que iOS inicie la aplicación móvil y pase la dirección URL como parámetro de inicio, donde se procesa mediante la OpenUrl invalidación de la clase de AppDelegate la aplicación y devuelve el control de la experiencia a MSAL. La OpenUrl implementación se muestra en el ejemplo de código siguiente:

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

En Android, el esquema de dirección URL personalizado que se registró con Azure Active Directory B2C debe estar registrado en el AndroidManifest.xml. MSAL espera que el esquema de dirección URL se ajuste a un patrón específico, descrito anteriormente en Registro de la aplicación móvil con Azure Active Directory B2C. En el ejemplo siguiente se muestra el esquema de dirección URL personalizado en el 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>

La MainActivity clase debe modificarse para proporcionar el UIParent objeto a la aplicación durante la OnCreate llamada. Cuando Azure Active Directory B2C completa la solicitud de autorización, se redirige al esquema de dirección URL registrado desde el AndroidManifest.xml. El esquema de URI registrado da como resultado que Android llame al OnActivityResult método con la dirección URL como parámetro de inicio, donde el método procesa SetAuthenticationContinuationEventArgs .

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 de Windows

No se requiere ninguna configuración adicional para usar MSAL en el Plataforma universal de Windows

Ejecución del proyecto

Ejecute la aplicación en un dispositivo virtual o físico. Al pulsar el botón Iniciar sesión, debe abrir el explorador y navegar a una página donde puede iniciar sesión o crear una cuenta. Después de completar el proceso de inicio de sesión, debe volver a la página de cierre de sesión de la aplicación. En la captura de pantalla siguiente se muestra la pantalla de inicio de sesión del usuario que se ejecuta en Android e iOS: