Compartir a través de


Adición de autenticación a la aplicación MAUI de .NET

Nota

Este producto se retira. Para obtener un reemplazo de proyectos con .NET 8 o posterior, consulte la biblioteca datasync de Community Toolkit.

En este tutorial, agregará la autenticación de Microsoft al proyecto TodoApp mediante el identificador de Microsoft Entra. Antes de completar este tutorial, asegúrese de que ha creado el proyecto e implementado elback-end.

Propina

Aunque usamos microsoft Entra ID para la autenticación, puede usar cualquier biblioteca de autenticación que desee con Azure Mobile Apps.

Adición de autenticación al servicio back-end

El servicio back-end es un servicio estándar ASP.NET 6. Cualquier tutorial que muestre cómo habilitar la autenticación para un servicio ASP.NET 6 funciona con Azure Mobile Apps.

Para habilitar la autenticación de Microsoft Entra para el servicio back-end, debe:

  • Registre una aplicación con el identificador de Entra de Microsoft.
  • Agregue la comprobación de autenticación al proyecto de back-end de ASP.NET 6.

Registro de la aplicación

En primer lugar, registre la API web en el inquilino de Microsoft Entra y agregue un ámbito siguiendo estos pasos:

  1. Inicie sesión en Azure Portal.

  2. Si tiene acceso a varios inquilinos, use el Directorios y suscripciones filtrar en el menú superior para cambiar al inquilino en el que desea registrar la aplicación.

  3. Busque y seleccione id. de Microsoft Entra.

  4. En Administrar, seleccione Registros de aplicaciones>Nuevo registro.

    • Nombre: escriba un nombre para la aplicación; por ejemplo, inicio rápido de TodoApp. Los usuarios de la aplicación verán este nombre. Puede cambiarlo más adelante.
    • tipos de cuenta admitidos: cuentas de en cualquier directorio organizativo (cualquier directorio de Microsoft Entra: multiinquilino) y cuentas microsoft personales (por ejemplo, Skype, Xbox)
  5. Seleccione Registrar.

  6. En Administrar, seleccione Exponer una API>Agregar un ámbito.

  7. Para URI de identificador de aplicación, acepte el valor predeterminado seleccionando Guardar y continuar.

  8. Escriba los detalles siguientes:

    • Nombre de ámbito: access_as_user
    • ¿Quién puede dar su consentimiento?: administradores y usuarios de
    • nombre para mostrar del consentimiento del administrador: Access TodoApp
    • Descripción del consentimiento del administrador: Allows the app to access TodoApp as the signed-in user.
    • Nombre para mostrar del consentimiento del usuario: Access TodoApp
    • Descripción del consentimiento del usuario: Allow the app to access TodoApp on your behalf.
    • state: habilitado
  9. Seleccione Agregar de ámbito para completar la adición del ámbito.

  10. Tenga en cuenta el valor del ámbito, similar a api://<client-id>/access_as_user (denominado ámbito de api web de ). Necesita el ámbito al configurar el cliente.

  11. Seleccione Información general.

  12. Anote la de id. de aplicación (cliente) de en la sección Essentials (denominada id. de aplicación de API web). Necesita este valor para configurar el servicio back-end.

Abra Visual Studio y seleccione el proyecto de TodoAppService.NET6.

  1. Haga clic con el botón derecho en el proyecto de TodoAppService.NET6 y seleccione Administrar paquetes NuGet....

  2. En la nueva pestaña, seleccione Examinary escriba Microsoft.Identity.Web en el cuadro de búsqueda.

    Captura de pantalla de cómo agregar M S A L NuGet en Visual Studio.

  3. Seleccione el paquete de Microsoft.Identity.Web y presione Instalar.

  4. Siga las indicaciones para completar la instalación del paquete.

  5. Abra Program.cs. Agregue lo siguiente a la lista de instrucciones using:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. Agregue el código siguiente directamente encima de la llamada a builder.Services.AddDbContext():
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. Agregue el código siguiente directamente encima de la llamada a app.MapControllers():
app.UseAuthentication();
app.UseAuthorization();

La Program.cs debería tener este aspecto:

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. Edite el Controllers\TodoItemController.cs. Agregue un atributo [Authorize] a la clase . La clase debe tener este aspecto:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. Edite el appsettings.json. Agregue el siguiente bloque:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

Reemplace el <client-id> por el identificador de aplicación de API web de que registró anteriormente. Una vez completado, debería tener este aspecto:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Vuelva a publicar el servicio en Azure:

  1. Haga clic con el botón derecho en el proyecto de TodoAppService.NET6 y seleccione Publicar....
  2. Seleccione el botón Publicar en la esquina superior derecha de la pestaña.

Abra un explorador para https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0. Tenga en cuenta que el servicio ahora devuelve una respuesta 401, lo que indica que se requiere autenticación.

Captura de pantalla del explorador que muestra un error.

Registro de la aplicación con el servicio de identidad

Microsoft Data Sync Framework tiene compatibilidad integrada con cualquier proveedor de autenticación que use un token web json (JWT) dentro de un encabezado de la transacción HTTP. Esta aplicación usa el de la biblioteca de autenticación de Microsoft (MSAL) de para solicitar este token y autorizar al usuario que ha iniciado sesión en el servicio back-end.

Configuración de una aplicación cliente nativa

Puede registrar clientes nativos para permitir la autenticación en las API web hospedadas en la aplicación mediante una biblioteca cliente, como la Biblioteca de identidades de Microsoft (MSAL).

  1. En azure Portal, seleccione Microsoft Entra ID>Registros de aplicaciones>Nuevo registro.

  2. En la página Registrar una aplicación:

    • escriba un Nombre para el registro de la aplicación. Es posible que quiera usar el nombre native-quickstart para distinguirlo del que usa el servicio back-end.
    • Seleccione Cuentas en cualquier directorio organizativo (cualquier directorio microsoft Entra - Multiinquilino) y cuentas microsoft personales (por ejemplo, Skype, Xbox).
    • En URI de redirección:
      • Seleccione cliente público (escritorio de & móvil)
      • Escriba la dirección URL quickstart://auth
  3. Seleccione Registrar.

  4. Seleccione permisos de API>Agregar un permiso>Mis API.

  5. Seleccione el registro de aplicaciones que creó anteriormente para el servicio back-end. Si no ve el registro de la aplicación, asegúrese de agregar el ámbito de access_as_user.

    Captura de pantalla del registro de ámbito en Azure Portal.

  6. En Seleccionar permisos, seleccione access_as_usery, a continuación, seleccione Agregar permisos.

  7. Seleccione Autenticación>aplicaciones móviles y de escritorio.

  8. Active la casilla situada junto a https://login.microsoftonline.com/common/oauth2/nativeclient.

  9. Active la casilla situada junto a msal{client-id}://auth (reemplazando {client-id} por el identificador de aplicación).

  10. Seleccione Agregar URIy agregue http://localhost en el campo para URI adicionales.

  11. Seleccione Guardar en la parte inferior de la página.

  12. Seleccione Información general. Anote la de id. de aplicación (cliente) de (denominada id. de aplicación de Native Client) según sea necesario para configurar la aplicación móvil.

Hemos definido tres direcciones URL de redireccionamiento:

  • las aplicaciones de WPF usan http://localhost.
  • las aplicaciones para UWP usan https://login.microsoftonline.com/common/oauth2/nativeclient.
  • las aplicaciones móviles (Android e iOS) usan msal{client-id}://auth.

Adición de Microsoft Identity Client a la aplicación

Abra la solución TodoApp.sln en Visual Studio y establezca el proyecto de TodoApp.MAUI como proyecto de inicio. Agregue el biblioteca de identidades de Microsoft (MSAL) al proyecto de :

Agregue el Biblioteca de identidades de Microsoft (MSAL) al proyecto de plataforma:

  1. Haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet....

  2. Seleccione la pestaña Examinar .

  3. Escriba Microsoft.Identity.Client en el cuadro de búsqueda y presione Entrar.

  4. Seleccione el resultado Microsoft.Identity.Client y haga clic en Instalar.

    Captura de pantalla de la selección de NuGet de MSAL en Visual Studio.

  5. Acepte el contrato de licencia para continuar con la instalación.

Agregue el identificador de cliente nativo y el ámbito de back-end a la configuración.

Abra el proyecto TodoApp.Data y edite el archivo Constants.cs. Agregue constantes para ApplicationId y Scopes:

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

Reemplace el <client-id> por el id. de aplicación de Native Client que recibió al registrar la aplicación cliente en el id. de Microsoft Entra y el <scope> por el ámbito de la API web de que copió al usar Exponer una API al registrar la aplicación de servicio.

Abra la clase MainPage.xaml.cs en el proyecto de TodoApp.MAUI. Agregue las siguientes instrucciones using:

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;

En la clase MainPage, agregue una nueva propiedad:

public IPublicClientApplication IdentityClient { get; set; }

Ajuste el constructor para leer:

public MainPage()
{
    InitializeComponent();
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    viewModel = new MainViewModel(this, TodoService);
    BindingContext = viewModel;
}

Agregue el método GetAuthenticationToken a la clase :

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
#if ANDROID
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => Platform.CurrentActivity)
            .Build();
#elif IOS
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .Build();
#else
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
            .Build();
#endif
    }

    var accounts = await IdentityClient.GetAccountsAsync();
    AuthenticationResult result = null;
    bool tryInteractiveLogin = false;

    try
    {
        result = await IdentityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        tryInteractiveLogin = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
    }

    if (tryInteractiveLogin)
    {
        try
        {
            result = await IdentityClient
                .AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
        }
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

El método GetAuthenticationToken() funciona con la Biblioteca de identidades de Microsoft (MSAL) para obtener un token de acceso adecuado para autorizar al usuario que ha iniciado sesión en el servicio back-end. A continuación, esta función se pasa al RemoteTodoService para crear el cliente. Si la autenticación se realiza correctamente, el AuthenticationToken se genera con los datos necesarios para autorizar cada solicitud. Si no es así, se genera un token incorrecto expirado en su lugar.

Podemos agregar cualquier opción específica de la plataforma mediante las áreas de #if con un especificador de plataforma. Por ejemplo, Android requiere que especifiquemos la actividad primaria, que se pasa desde la página de llamada.

Configuración de la aplicación Android para la autenticación

Cree una nueva clase Platforms\Android\MsalActivity.cs con el código siguiente:

using Android.App;
using Android.Content;
using Microsoft.Identity.Client;

namespace TodoApp.MAUI
{
    [Activity(Exported = true)]
    [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client-id}")]
    public class MsalActivity : BrowserTabActivity
    {
    }
}

Reemplace {client-id} por el identificador de aplicación del cliente nativo (que es el mismo que Constants.ApplicationId).

Si el proyecto tiene como destino Android versión 11 (versión 30 de API) o posterior, debe actualizar el AndroidManifest.xml para cumplir los requisitos de visibilidad de paquetes android . Abra Platforms/Android/AndroidManifest.xml y agregue los siguientes nodos queries/intent al nodo manifest:

<manifest>
  ...
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

Abra MauiProgram.cs. Incluya las siguientes instrucciones using en la parte superior del archivo:

using Microsoft.Identity.Client;

Actualice el generador al código siguiente:

    builder
        .UseMauiApp<App>()
        .ConfigureLifecycleEvents(events =>
        {
#if ANDROID
            events.AddAndroid(platform =>
            {
                platform.OnActivityResult((activity, rc, result, data) =>
                {
                    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(rc, result, data);
                });
            });
#endif
        })
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

Si va a realizar este paso después de actualizar la aplicación para iOS, agregue el código designado por el #if ANDROID (incluido el #if y #endif). El compilador elige el fragmento de código correcto en función de la plataforma que se está compilando. Este código se puede colocar antes o después del bloque existente para iOS.

Cuando Android requiere autenticación, obtiene un cliente de identidad y, a continuación, cambia a una actividad interna que abre el explorador del sistema. Una vez completada la autenticación, el explorador del sistema redirige a la dirección URL de redireccionamiento definida (msal{client-id}://auth). El MsalActivity intercepta la dirección URL de redireccionamiento, que luego vuelve a la actividad principal llamando a OnActivityResult(). El método OnActivityResult() llama al asistente de autenticación msal para completar la transacción.

Prueba de la aplicación Android

Establezca TodoApp.MAUI como proyecto de inicio, seleccione un emulador de Android como destino y presione F5 para compilar y ejecutar la aplicación. Cuando se inicie la aplicación, se le pedirá que inicie sesión en la aplicación. En la primera ejecución, se le pide que dé su consentimiento a la aplicación. Una vez completada la autenticación, la aplicación se ejecuta como normal.

Prueba de la aplicación de Windows

Establezca TodoApp.MAUI como proyecto de inicio, seleccione máquina Windows como destino y presione F5 para compilar y ejecutar la aplicación. Cuando se inicie la aplicación, se le pedirá que inicie sesión en la aplicación. En la primera ejecución, se le pide que dé su consentimiento a la aplicación. Una vez completada la autenticación, la aplicación se ejecuta como normal.

Pasos siguientes

A continuación, configure la aplicación para que funcione sin conexión implementando un almacén sin conexión.

Lectura adicional