Usare Touch ID e Face ID con Xamarin.iOS

iOS supporta due sistemi di autenticazione biometrica:

  1. Touch ID usa un sensore di impronta digitale sotto il pulsante Home.
  2. Face ID usa sensori di fotocamera front-face per autenticare gli utenti con una scansione facciale.

Touch ID è stato introdotto in iOS 7 e Face ID in iOS 11.

Questi sistemi di autenticazione si basano su un processore di sicurezza basato su hardware denominato Enclave sicuro. L'enclave sicuro è responsabile della crittografia delle rappresentazioni matematiche dei dati relativi a viso e impronta digitale e dell'autenticazione degli utenti usando queste informazioni. Secondo Apple, i dati relativi a viso e impronta digitale non lasciano il dispositivo e non vengono sottoposti a backup in iCloud. Le app interagiscono con l'enclave sicuro tramite l'API di autenticazione locale e non possono recuperare i dati relativi a viso o impronta digitale o accedere direttamente all'enclave sicuro.

Touch ID e Face ID possono essere usati dalle app per autenticare un utente prima di fornire l'accesso al contenuto protetto.

Contesto di autenticazione locale

L'autenticazione biometrica in iOS si basa su un oggetto contesto di autenticazione locale, ovvero un'istanza della LAContext classe . La LAContext classe consente di:

  • Controllare la disponibilità dell'hardware biometrico.
  • Valutare i criteri di autenticazione.
  • Valutare i controlli di accesso.
  • Personalizzare e visualizzare le richieste di autenticazione.
  • Riutilizzare o invalidare uno stato di autenticazione.
  • Gestire le credenziali.

Rilevare i metodi di autenticazione disponibili

Il progetto di esempio include un AuthenticationView oggetto supportato da un oggetto AuthenticationViewController. Questa classe esegue l'override del ViewWillAppear metodo per rilevare i metodi di autenticazione disponibili:

partial class AuthenticationViewController: UIViewController
{
    // ...
    string BiometryType = "";

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        unAuthenticatedLabel.Text = "";

        var context = new LAContext();
        var buttonText = "";

        // Is login with biometrics possible?
        if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out var authError1))
        {
            // has Touch ID or Face ID
            if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
            {
                context.LocalizedReason = "Authorize for access to secrets"; // iOS 11
                BiometryType = context.BiometryType == LABiometryType.TouchId ? "Touch ID" : "Face ID";
                buttonText = $"Login with {BiometryType}";
            }
            // No FaceID before iOS 11
            else
            {
                buttonText = $"Login with Touch ID";
            }
        }

        // Is pin login possible?
        else if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, out var authError2))
        {
            buttonText = $"Login"; // with device PIN
            BiometryType = "Device PIN";
        }

        // Local authentication not possible
        else
        {
            // Application might choose to implement a custom username/password
            buttonText = "Use unsecured";
            BiometryType = "none";
        }
        AuthenticateButton.SetTitle(buttonText, UIControlState.Normal);
    }
}

Il ViewWillAppear metodo viene chiamato quando l'interfaccia utente sta per essere visualizzata all'utente. Questo metodo definisce una nuova istanza di LAContext e usa il CanEvaluatePolicy metodo per determinare se l'autenticazione biometrica è abilitata. In tal caso, controlla la versione del sistema e l'enumerazione BiometryType per determinare quali opzioni biometriche sono disponibili.

Se l'autenticazione biometrica non è abilitata, l'app tenta di eseguire il fallback all'autenticazione PIN. Se non è disponibile né l'autenticazione biometrica né il PIN, il proprietario del dispositivo non ha abilitato le funzionalità di sicurezza e il contenuto non può essere protetto tramite l'autenticazione locale.

Autenticare un utente

AuthenticationViewController Nel progetto di esempio è incluso un AuthenticateMe metodo, che è responsabile dell'autenticazione dell'utente:

partial class AuthenticationViewController: UIViewController
{
    // ...
    string BiometryType = "";

    partial void AuthenticateMe(UIButton sender)
    {
        var context = new LAContext();
        NSError AuthError;
        var localizedReason = new NSString("To access secrets");

        // Because LocalAuthentication APIs have been extended over time,
        // you must check iOS version before setting some properties
        context.LocalizedFallbackTitle = "Fallback";

        if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
        {
            context.LocalizedCancelTitle = "Cancel";
        }
        if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
        {
            context.LocalizedReason = "Authorize for access to secrets";
            BiometryType = context.BiometryType == LABiometryType.TouchId ? "TouchID" : "FaceID";
        }

        // Check if biometric authentication is possible
        if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out AuthError))
        {
            replyHandler = new LAContextReplyHandler((success, error) =>
            {
                // This affects UI and must be run on the main thread
                this.InvokeOnMainThread(() =>
                {
                    if (success)
                    {
                        PerformSegue("AuthenticationSegue", this);
                    }
                    else
                    {
                        unAuthenticatedLabel.Text = $"{BiometryType} Authentication Failed";
                    }
                });

            });
            context.EvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason, replyHandler);
        }

        // Fall back to PIN authentication
        else if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, out AuthError))
        {
            replyHandler = new LAContextReplyHandler((success, error) =>
            {
                // This affects UI and must be run on the main thread
                this.InvokeOnMainThread(() =>
                {
                    if (success)
                    {
                        PerformSegue("AuthenticationSegue", this);
                    }
                    else
                    {
                        unAuthenticatedLabel.Text = "Device PIN Authentication Failed";
                        AuthenticateButton.Hidden = true;
                    }
                });

            });
            context.EvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, localizedReason, replyHandler);
        }

        // User hasn't configured any authentication: show dialog with options
        else
        {
            unAuthenticatedLabel.Text = "No device auth configured";
            var okCancelAlertController = UIAlertController.Create("No authentication", "This device does't have authentication configured.", UIAlertControllerStyle.Alert);
            okCancelAlertController.AddAction(UIAlertAction.Create("Use unsecured", UIAlertActionStyle.Default, alert => PerformSegue("AuthenticationSegue", this)));
            okCancelAlertController.AddAction(UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, alert => Console.WriteLine("Cancel was clicked")));
            PresentViewController(okCancelAlertController, true, null);
        }
    }
}

Il AuthenticateMe metodo viene chiamato in risposta all'utente toccando un pulsante Login . Viene creata un'istanza di un nuovo LAContext oggetto e viene verificata la versione del dispositivo per determinare le proprietà da impostare nel contesto di autenticazione locale.

Il CanEvaluatePolicy metodo viene chiamato per verificare se l'autenticazione biometrica è abilitata, eseguire il fallback all'autenticazione PIN, se possibile, e infine offrire una modalità non protetta se non è disponibile alcuna autenticazione. Se è disponibile un metodo di autenticazione, il EvaluatePolicy metodo viene usato per visualizzare l'interfaccia utente e completare il processo di autenticazione.

Il progetto di esempio contiene dati fittizi e una visualizzazione per visualizzare i dati se l'autenticazione ha esito positivo.