Xamarin.Essentials: Autenticador web

La clase WebAuthenticator permite iniciar flujos basados en explorador que escuchan una devolución de llamada a una dirección URL específica registrada en la aplicación.

Información general

Muchas aplicaciones requieren la adición de la autenticación de usuario y esto suele significar permitir que los usuarios inicien sesión en sus cuentas de inicio de sesión existentes de Microsoft, Facebook, Google y ahora Apple.

La biblioteca de autenticación de Microsoft (MSAL) proporciona una excelente solución llave en mano para agregar la autenticación a la aplicación. Hay incluso compatibilidad con las aplicaciones de Xamarin en su paquete NuGet de cliente.

Si le interesa usar su propio servicio web para la autenticación, es posible usar WebAuthenticator para implementar la funcionalidad del lado cliente.

¿Por qué usar un back-end de servidor?

Muchos proveedores de autenticación han pasado a ofrecer solo flujos de autenticación explícitos o de dos segmentos para garantizar una mayor seguridad. Esto significa que necesitará un "secreto de cliente" del proveedor para completar el flujo de autenticación. Lamentablemente, las aplicaciones móviles no son un lugar ideal para almacenar secretos y todo lo que se almacena en el código o los archivos binarios de una aplicación móvil o, en caso contrario, se considera que no son seguros a nivel general.

El procedimiento recomendado es usar un back-end web como una capa intermedia entre su aplicación móvil y el proveedor de autenticación.

Importante

Se recomienda encarecidamente usar patrones y bibliotecas de autenticación anteriores destinados exclusivamente para móviles y que no usen un back-end web en el flujo de autenticación, debido a la falta de seguridad inherente para almacenar secretos de cliente.

Primeros pasos

Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que la biblioteca está correctamente instalada y configurada en los proyectos.

Para acceder a la funcionalidad de WebAuthenticator, se requiere la siguiente configuración específica para la plataforma.

Android requiere una configuración del filtro de intención para controlar el identificador URI de devolución de llamada. Esto se realiza con facilidad mediante la creación de subclases de la clase WebAuthenticatorCallbackActivity:

const string CALLBACK_SCHEME = "myapp";

[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
    Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
    DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}

Si la versión de Android de destino del proyecto se establece en Android 11 (R API 30) , debe actualizar el manifiesto de Android con las consultas que se usan con los nuevos requisitos de visibilidad de los paquetes.

Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo manifest:

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

Uso de WebAuthenticator

Agregue una referencia a Xamarin.Essentials en la clase:

using Xamarin.Essentials;

La API se compone principalmente de un único método AuthenticateAsync que adopta dos parámetros: la dirección URL que se debe usar para iniciar el flujo del explorador web y el identificador URI al que se espera que el flujo devuelva la llamada en última instancia y en la que la aplicación debe estar registrada para poder realizar el control.

El resultado es un elemento WebAuthenticatorResult que incluye todos los parámetros de consulta analizados desde el identificador URI de devolución de llamada:

var authResult = await WebAuthenticator.AuthenticateAsync(
        new Uri("https://mysite.com/mobileauth/Microsoft"),
        new Uri("myapp://"));

var accessToken = authResult?.AccessToken;

La API WebAuthenticator se encarga de iniciar la dirección URL en el explorador y esperar a que se reciba la devolución de llamada:

Typical Web Authentication Flow

Si el usuario cancela el flujo en cualquier momento, se devuelve una excepción TaskCanceledException.

Sesión de autenticación privada

Con iOS 13, se introdujo una API de explorador web efímera con la que los desarrolladores pueden iniciar la sesión de autenticación como privada. Esto les permite solicitar que no haya cookies compartidas ni datos de exploración disponibles entre sesiones de autenticación y que cada inicio de sesión sea nuevo. Está disponible con WebAuthenticatorOptions, una novedad de Xamarin.Essentials 1.7 para iOS.

var url = new Uri("https://mysite.com/mobileauth/Microsoft");
var callbackUrl = new Uri("myapp://");
var authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
    {
        Url = url,
        CallbackUrl = callbackUrl,
        PrefersEphemeralWebBrowserSession = true
    });

Diferencias entre plataformas

Las pestañas personalizadas se usan siempre que estén disponibles; de lo contrario, se inicia una intención para la dirección URL.

Inicio de sesión de Apple

Según las directrices de revisión de Apple, si su aplicación usa cualquier servicio de inicio de sesión social para autenticarse, también debe ofrecer el inicio de sesión de Apple como una opción.

Para agregar el inicio de sesión de Apple a sus aplicaciones, primero necesitará configurar la aplicación para que use el inicio de sesión de Apple.

Para iOS 13 y versiones posteriores, deberá llamar al método AppleSignInAuthenticator.AuthenticateAsync(). De este modo, se usará la API de inicio de sesión de Apple nativa de forma subyacente para que los usuarios obtengan la mejor experiencia posible en estos dispositivos. Puede escribir el código compartido para usar la API correcta en tiempo de ejecución de la siguiente manera:

var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;

if (scheme.Equals("Apple")
    && DeviceInfo.Platform == DevicePlatform.iOS
    && DeviceInfo.Version.Major >= 13)
{
    // Use Native Apple Sign In API's
    r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
    // Web Authentication flow
    var authUrl = new Uri(authenticationUrl + scheme);
    var callbackUrl = new Uri("xamarinessentials://");

    r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}

var authToken = string.Empty;
if (r.Properties.TryGetValue("name", out var name) && !string.IsNullOrEmpty(name))
    authToken += $"Name: {name}{Environment.NewLine}";
if (r.Properties.TryGetValue("email", out var email) && !string.IsNullOrEmpty(email))
    authToken += $"Email: {email}{Environment.NewLine}";

// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += r?.AccessToken ?? r?.IdToken;

Sugerencia

En el caso de dispositivos que no son iOS 13, se iniciará el flujo de autenticación web, que también se puede usar para habilitar el inicio de sesión de Apple en los dispositivos Android y UWP. Puede iniciar sesión en su cuenta de iCloud en el simulador de iOS para probar el inicio de sesión de Apple.


Back-end de servidor de ASP.NET Core

Es posible usar la API WebAuthenticator con cualquier servicio back-end web. Para usarla con una aplicación de ASP.NET Core, primero debe configurar la aplicación web con los pasos siguientes:

  1. Configure los proveedores de autenticación social externos que desee en una aplicación web de ASP.NET Core.
  2. Establezca el esquema de autenticación predeterminado en CookieAuthenticationDefaults.AuthenticationScheme en la llamada .AddAuthentication().
  3. Use .AddCookie() en la llamada .AddAuthentication() de Startup.cs.
  4. Todos los proveedores deben configurarse con .SaveTokens = true;.
services.AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddFacebook(fb =>
    {
        fb.AppId = Configuration["FacebookAppId"];
        fb.AppSecret = Configuration["FacebookAppSecret"];
        fb.SaveTokens = true;
    });

Sugerencia

Si desea incluir el inicio de sesión de Apple, puede usar el paquete NuGet AspNet.Security.OAuth.Apple. Puede ver el ejemplo de Startup.cs completo en el repositorio de GitHub de Essentials.

Agregar un controlador de autenticación móvil personalizado

Con un flujo de autenticación móvil, suele ser conveniente iniciar el flujo directamente en un proveedor que el usuario ha elegido (por ejemplo, haciendo clic en un botón de "Microsoft" en la pantalla de inicio de sesión de la aplicación). También es importante poder devolver información relevante a la aplicación en un identificador URI de devolución de llamada específico para finalizar el flujo de autenticación.

Para ello, use un controlador de API personalizado:

[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
    const string callbackScheme = "myapp";

    [HttpGet("{scheme}")] // eg: Microsoft, Facebook, Apple, etc
    public async Task Get([FromRoute]string scheme)
    {
        // 1. Initiate authentication flow with the scheme (provider)
        // 2. When the provider calls back to this URL
        //    a. Parse out the result
        //    b. Build the app callback URL
        //    c. Redirect back to the app
    }
}

El propósito de este controlador es deducir el esquema (proveedor) que la aplicación está solicitando e iniciar el flujo de autenticación con el proveedor social. Cuando el proveedor devuelve la llamada al back-end web, el controlador analiza el resultado y redirige al identificador URI de devolución de llamada de la aplicación con parámetros.

En ocasiones, puede que desee devolver datos como el elemento access_token del proveedor a la aplicación, algo que se puede hacer con los parámetros de consulta del identificador URI de devolución de llamada. O bien, puede que desee crear su propia identidad en el servidor y pasar su propio token a la aplicación. En qué y hasta qué punto puede intervenir el usuario.

Consulte el ejemplo del controlador completo en el repositorio de Essentials.

Nota:

En el ejemplo anterior, se muestra cómo devolver el token de acceso desde el proveedor de autenticación de terceros (es decir: OAuth). Para obtener un token que pueda usar para autorizar solicitudes web al propio back-end web, debe crear su propio token en la aplicación web y devolverlo en su lugar. En Información general sobre la autenticación de ASP.NET Core se ofrece más información sobre los escenarios de autenticación avanzada en ASP.NET Core.


API