Adición de la autenticación a la aplicación Xamarin.iOS

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 el back-end.

Nota:

Dado que la aplicación de iOS requiere acceso a la cadena de claves, deberá configurar un perfil de aprovisionamiento de iOS. Un perfil de aprovisionamiento requiere un dispositivo iOS real o una cuenta de desarrollador de Apple de pago (si usa el simulador). Puede omitir este tutorial y pasar a agregar acceso sin conexión a la aplicación si no puede usar la autenticación debido a esta restricción.

Sugerencia

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:

  • Registrar una aplicación con Microsoft Entra ID.
  • 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 filtro Directorios y suscripciones en el menú superior para cambiar al inquilino en el que desea registrar la aplicación.

  3. Busque y seleccione Microsoft Entra ID.

  4. En Administrar, seleccione Registros de aplicaciones> y, luego, 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 tarde.
    • Tipos de cuenta admitidos: cuentas en cualquier directorio organizativo (cualquier directorio microsoft Entra : multiinquilino) y cuentas personales de Microsoft (por ejemplo, Skype, Xbox)
  5. Seleccione Registrar.

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

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

  8. Escriba la siguiente información:

    • Nombre de ámbito: access_as_user
    • ¿Quién puede dar el consentimiento? : Administradores y usuarios
    • 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.
    • Estado: Enabled
  9. Seleccione Agregar ámbito para completar la adición del ámbito.

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

  11. Seleccione Información general.

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

Abra Visual Studio y seleccione el TodoAppService.NET6 proyecto.

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

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

    Screenshot of adding the M S A L NuGet in Visual Studio.

  3. Seleccione el Microsoft.Identity.Web paquete 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 using instrucciones:

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

Program.cs ahora debería presentar un aspecto similar a este:

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 .Controllers\TodoItemController.cs Agregue un [Authorize] atributo 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 .appsettings.json Agregue el siguiente bloque:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

Reemplace por <client-id> el identificador de aplicación de API web 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 TodoAppService.NET6 proyecto y seleccione Publicar....
  2. Seleccione el botón Publicar en la esquina superior derecha de la pestaña.

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

Screenshot of the browser showing an 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 la Biblioteca de autenticación de Microsoft (MSAL) para solicitar este token y autorizar al usuario que ha iniciado sesión en el servicio back-end.

Configuración de una aplicación de cliente nativo

Puede registrar clientes nativos para permitir la autenticación en las API web hospedadas en la aplicación con una biblioteca cliente como la Biblioteca de identidad 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 personales de Microsoft (por ejemplo, Skype, Xbox) .
    • En URI de redirección:
      • Seleccionar cliente público (móvil y escritorio)
      • Escriba la dirección URL. quickstart://auth
  3. Seleccione Registrar.

  4. Seleccione Permisos de API>Agregar 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 .

    Screenshot of the scope registration in the Azure portal.

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

  7. Seleccione Authentication Mobile and desktop applications (Autenticación>de 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 URI y agregue http://localhost el campo para URI adicionales.

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

  12. Seleccione Información general. Anote el identificador de aplicación (cliente) (denominado id. de aplicación de Native Client) como necesita para configurar la aplicación móvil.

Hemos definido tres direcciones URL de redireccionamiento:

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

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

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

Agregue la 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, luego, presione Entrar.

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

    Screenshot of selecting the MSAL NuGet in 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 TodoApp.Data proyecto y edite el Constants.cs archivo. 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 por <client-id> el identificador de aplicación de Native Client que recibió al registrar la aplicación cliente en microsoft Entra ID y por <scope> el ámbito de la API web que copió cuando usó Exponer una API al registrar la aplicación de servicio.

Abra ViewControllers\HomeViewController.cs en el TodoApp.iOS proyecto. Agregue las instrucciones siguientes using :

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

En la HomeViewController clase , agregue una nueva propiedad:

public IPublicClientApplication IdentityClient { get; set; }

Ajuste el constructor para leer:

public HomeViewController() {
  Title = "Todo Items";
  TodoService = new RemoteTodoService(GetAuthenticationToken);
  TodoService.TodoItemsUpdated += OnTodoItemsUpdated;
}

Agregue el método GetAuthenticationToken a la clase:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
        IdentityClient = PublicClientApplicationBuilder.Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
            .Build();
    }

    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()
                .ConfigureAwait(false);
        }
        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 GetAuthenticationToken() método 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 objeto para crear el cliente. Si la autenticación se realiza correctamente, AuthenticationToken se genera con los datos necesarios para autorizar cada solicitud. Si no es así, se genera un token incorrecto expirado en su lugar.

Agregue el código siguiente a la parte inferior de la AppDelegate clase :

[Export("application:openURL:options:")]
public bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return true;
}

Agregue acceso a la cadena de claves a Entitlements.plist:

  1. Abra el archivo Entitlements.plist.

  2. Seleccione Llavero.

  3. Seleccione Agregar nuevo en los grupos de cadenas de claves.

  4. Escriba com.microsoft.adalcache como valor:

    Screenshot showing the i O S entitlements.

Agregue los derechos personalizados al proyecto:

  1. Haga clic con el botón derecho en el TodoApp.iOS proyecto y seleccione Propiedades.

  2. Seleccione Firma de lote de iOS.

  3. Seleccione el botón ... situado junto al campo Derechos personalizados .

  4. Seleccione Entitlementsy, a continuación, seleccione Abrir.

  5. Presione Ctrl+S para guardar el proyecto.

    Screenshot showing the i O S bundle signing properties.

Prueba de la aplicación

Nota:

Dado que la aplicación de iOS requiere acceso a la cadena de claves, deberá configurar un perfil de aprovisionamiento. Un perfil de aprovisionamiento requiere un dispositivo real o una cuenta de desarrollador de Apple de pago (si usa el simulador).

Establezca TodoApp.iOS como proyecto de inicio y, a continuación, compile y ejecute 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 mediante la implementación de un almacén sin conexión.

Información adicional