Adición de autenticación a la aplicación de Xamarin.Android
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:
Inicie sesión en Azure Portal.
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.
Busque y seleccione id. de Microsoft Entra.
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)
Seleccione Registrar.
En Administrar, seleccione Exponer una API>Agregar un ámbito.
Para URI de identificador de aplicación, acepte el valor predeterminado seleccionando Guardar y continuar.
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
-
Nombre de ámbito:
Seleccione Agregar de ámbito para completar la adición del ámbito.
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.Seleccione Información general.
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
.
Haga clic con el botón derecho en el proyecto de
TodoAppService.NET6
y seleccione Administrar paquetes NuGet....En la nueva pestaña, seleccione Examinary escriba Microsoft.Identity.Web en el cuadro de búsqueda.
Seleccione el paquete de
Microsoft.Identity.Web
y presione Instalar.Siga las indicaciones para completar la instalación del paquete.
Abra
Program.cs
. Agregue lo siguiente a la lista de instruccionesusing
:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
- 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();
- 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();
- 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))
{
}
}
}
- 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:
- Haga clic con el botón derecho en el proyecto de
TodoAppService.NET6
y seleccione Publicar.... - 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.
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
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).
En azure Portal, seleccione Microsoft Entra ID>Registros de aplicaciones>Nuevo registro.
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
- escriba un Nombre para el registro de la aplicación. Es posible que quiera usar el nombre
Seleccione Registrar.
Seleccione permisos de API>Agregar un permiso>Mis API.
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.
En Seleccionar permisos, seleccione access_as_usery, a continuación, seleccione Agregar permisos.
Seleccione Autenticación>aplicaciones móviles y de escritorio.
Active la casilla situada junto a
https://login.microsoftonline.com/common/oauth2/nativeclient
.Active la casilla situada junto a
msal{client-id}://auth
(reemplazando{client-id}
por el identificador de aplicación).Seleccione Agregar URIy agregue
http://localhost
en el campo para URI adicionales.Seleccione Guardar en la parte inferior de la página.
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.Android
como proyecto de inicio. Agregue el biblioteca de identidades de Microsoft (MSAL)
Agregue el
Haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet....
Seleccione la pestaña Examinar
. Escriba
Microsoft.Identity.Client
en el cuadro de búsqueda y presione Entrar.Seleccione el resultado
Microsoft.Identity.Client
y haga clic en Instalar.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 el archivo MainActivity.cs
en el proyecto de TodoApp.Android
. En la parte superior del archivo, agregue las siguientes instrucciones using:
using Android.Content;
using Microsoft.Identity.Client;
using Microsoft.Datasync.Client;
using System.Linq;
using System.Threading.Tasks;
using Debug = System.Diagnostics.Debug;
En la parte superior de la clase MainActivity
, agregue el siguiente campo:
public IPublicClientApplication identityClient;
En el método OnCreate()
, cambie la definición del TodoService
:
TodoService = new RemoteTodoService(GetAuthenticationToken);
Agregue el código siguiente para definir el método GetAuthenticationToken()
:
public async Task<AuthenticationToken> GetAuthenticationToken()
{
if (identityClient == null)
{
identityClient = PublicClientApplicationBuilder.Create(Constants.ApplicationId)
.WithAuthority(AzureCloudInstance.AzurePublic, "common")
.WithRedirectUri($"msal{Constants.ApplicationId}://auth")
.WithParentActivityOrWindow(() => this)
.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 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.
Para controlar la devolución de llamada desde el cliente de identidad, agregue el método siguiente:
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Return control to MSAL
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
Cree una nueva clase MsalActivity
con el código siguiente:
using Android.App;
using Android.Content;
using Microsoft.Identity.Client;
namespace TodoApp.Android
{
[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 Properties/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>
Prueba de la aplicación
Ejecute o reinicie la aplicación.
Cuando se ejecuta la aplicación, se abre un explorador para solicitar la autenticación. Si no se ha autenticado con la aplicación antes, la aplicación le pide que dé su consentimiento. Una vez completada la autenticación, el explorador del sistema se cierra y la aplicación se ejecuta como antes.
Pasos siguientes
A continuación, configure la aplicación para que funcione sin conexión implementando un almacén sin conexión.