次の方法で共有


Xamarin.iOS で Touch ID と Face ID を使用する

iOS では、次の 2 つの生体認証システムがサポートされています。

  1. Touch ID では、[ホーム] ボタンの下にある指紋センサーを使用します。
  2. Face ID では、前面カメラのセンサーを使用して、顔スキャンでユーザーを認証します。

Touch ID は iOS 7 で導入され、 Face ID は iOS 11 で導入されました。

これらの認証システムは、セキュリティで保護されたエンクレーブと呼ばれるハードウェア ベースのセキュリティ プロセッサに依存します。 セキュリティで保護されたエンクレーブは、顔データと指紋データの数学的表現を暗号化し、この情報を使用してユーザーを認証する役割を担います。 Apple によると、顔データと指紋データはデバイスに残り、iCloud にバックアップされることはありません。 アプリは、ローカル認証 API を通じてセキュリティで保護されたエンクレーブを操作し、顔データや指紋データを取得したり、セキュリティで保護されたエンクレーブに直接アクセスしたりすることはできません。

Touch ID と Face ID は、保護されたコンテンツへのアクセスを提供する前に、アプリがユーザーを認証するために使用できます。

ローカル認証コンテキスト

iOS の生体認証は、LAContext クラスのインスタンスであるローカル認証コンテキスト オブジェクトに依存します。 LAContext クラスでは、次のようなことができます。

  • 生体認証ハードウェアの可用性を確認します。
  • 認証ポリシーを評価します。
  • アクセス制御を評価します。
  • 認証プロンプトをカスタマイズして表示します。
  • 認証状態を再利用または無効化します。
  • 資格情報を管理します。

使用可能な認証方法を検出します。

サンプル プロジェクトには、AuthenticationViewController でサポートされた AuthenticationView が含まれます。 このクラスは、使用可能な認証方法を検出するために ViewWillAppear メソッドをオーバーライドします。

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

ViewWillAppear メソッドは、UI をユーザーに表示しようとしているときに呼び出されます。 このメソッドは、LAContext の新しいインスタンスを定義し、CanEvaluatePolicy メソッドを使用して、生体認証が有効になっているかどうかを判断します。 その場合は、システム バージョンと BiometryType 列挙型を確認して、使用可能な生体認証オプションを決定します。

生体認証が有効になっていない場合、アプリは PIN 認証へのフォールバックを試みます。 生体認証も PIN 認証も使用できない場合、デバイス所有者はセキュリティ機能を有効にしていないため、ローカル認証でコンテンツを保護することはできません。

ユーザーを認証する

サンプル プロジェクトの AuthenticationViewController には、ユーザーの認証を担当する AuthenticateMe メソッドが含まれます。

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

AuthenticateMe メソッドは、ユーザーが [ログイン] ボタンをタップした場合に応答して呼び出されます。 新しい LAContext オブジェクトがインスタンス化され、デバイスのバージョンがチェックされて、ローカル認証コンテキストで設定するプロパティが決定されます。

CanEvaluatePolicy メソッドは、生体認証が有効かどうかをチェックするために呼び出され、可能であれば PIN 認証にフォールバックし、最後に認証が使用できない場合はセキュリティで保護されていないモードを提供します。 認証方法が使用可能な場合、EvaluatePolicy メソッドを使用して UI を表示し、認証プロセスを完了します。

サンプル プロジェクトには、認証が成功した場合にデータを表示するモック データとビューが含まれています。