Adding TouchID and FaceID to a Xamarin.iOS Application
This is gonna be quick
Let’s imagine that you already have some login functionality in place inside your application so we can focus on the task at hand: implementing biometrics inside the iOS application. Basically either TouchID or FaceID, depending on what is supported by the device (iPhone 5s to iPhone 8 support TouchID and iPhone X, XR, XS and XS Max support FaceID).
Quick setup
You want to use this biometric authentication only after you have identified your user (meaning they have signed into your service at least once with their credentials). So you will have to make your users login “traditionally” at least once, and then save whatever information you need to authenticate them later (a key, an id, a hash, it depends on your authentication mechanism).
The functionality
So once you have authenticated your user at least once, if you want to help them quickly login without the need for them to type their password constantly, add a method that first tries to authenticate them using biometrics, and if it fails (and only if it fails) go back to the “traditional” type-your-password functionality.
Again, the implementation and the flow of this functionality will greatly depend on your application, but basically here is the method:
private void BiometricsAuth() { NSError error; var context = new LAContext(); if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out error)) { InvokeOnMainThread(async () => { try { var result = await context.EvaluatePolicyAsync(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, "Login"); if (result.Item1) { hasLoggedin = true; PerformSegue("loginSegue", this); } else { TraditionalLogin(); } } catch (Exception ex) { var alert = UIAlertController.Create("Failure", ex.Message, UIAlertControllerStyle.Alert); alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null)); PresentViewController(alert, true, null); } }); } else TraditionalLogin(); }
Basically the LAContext (for which you will need a using directive to the LocalAuthentication namespace) will handle everything through the EvaluatePolicyAsync method. It is very important that this method gets executed inside the main thread, which is why I have that InvokeOnMainThread block of code in the middle of this method.
It is also a great idea to first make sure that the current device supports biometrics, since there are still some devices out there that don’t have neither TouchID nor FaceID (such as the iPad Mini 2, the iPhone 5, iPhone 5C, and some others). Which is why I use the CanEvaluatePolicy method from the context before invoking the main thread.
Fairly obvious it is the DeviceOwnerAuthenticationWithBiometrics the one that you should use, there is a DeviceOwnerAuthentication but that won’t work with biometrics.
Final FaceID touches
Apple is for whatever reason a bit more wary when it comes to FaceID. Your application should first request the user permission to use FaceID to log them in. Maybe because FaceID can be a bit more “invisible” than TouchID since it requires the user to literally just stare into their phones (which they are probably already doing) instead of moving their thumb over to a sensor.
For this reason we must add an additional entry to the info.plist file that will let the user know why we need access to their face (this sounds so cool). Simply add a new “NSFaceIDUsageDescription” entry and a small message such as:
We will use FaceID to log you in with out the need for you to type your email and password.
The result of running your code on a TouchID-enabled device will be that the app requests the user to scan their fingerprint. On a FaceID-enabled device, this pop-up with our message will appear first:
So there you have it. I hope this post was useful!