How to use Touch ID in iOS 8

Screen Shot 2015-09-23 at 15.58.11

Since iOS 8 we can use the Touch ID sensors in compatible devices and authenticate sensitive data in our own apps. Here’s how to do it, short and simple.

Framework

First we’ll need to add the Local Authentication Framework to our app. To do that, navigate to your target and find the Linked Framework and Libraries section at the bottom. Click that little plus icon and search for “local”.

Screen Shot 2015-09-23 at 11.27.02

Code

Now that the framework is linked, we’ll need to import it into the class that does the verifying. I’ll use a simple view controller from the Single View application template here.

@import LocalAuthentication;

Nice. Now I’ll hook up an action to which the authentication can be triggered. Here’s what it looks like when we’re done:

- (IBAction)authenticateTouchID {
    
    // create a context and error object
    LAContext *context = [[LAContext alloc]init];
    NSError *error = nil;
    NSString *reason = @"We want to authenticate your fingerprints";
    
    // check if the device supports Touch ID
    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
        
        NSLog(@"Device supports Touch ID");
        
        // authenticate the user
        [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:reason reply:^(BOOL success, NSError * _Nullable error) {
            
            // it worked!
            if (success) {
                NSLog(@"Successfully authenticated the user via Touch ID. HUZZAH!");
            } else {
                NSLog(@"Could not authenticate the user via Touch ID. \nReason: %@ \nError Code: %ld", error.localizedDescription, error.code);
                
                // if the user chooses the password option
                if (error.code == -3) {
                    // handle password input here
                    NSLog(@"Let's ask for your password instead");
                }
            }
        }];
        
    } else {
        // Touch ID is not available
        NSLog(@"Touch ID is not available.");
    }
}

It looks a little scary, so let’s sift through this one step at a time. At the beginning we’ll create a Local Authentication Context. It’s just a class with one particular method we can call. We’ll also create an error object and a string that will appear as the message when the Touch ID view is brought up. The error allows us to check why Touch ID was not available at the end of our message if we so desire.

    // create a context and error object
    LAContext *context = [[LAContext alloc]init];
    NSError *error = nil;
    NSString *reason = @"We want to authenticate your fingerprints";

Next up we’ll check if Touch ID is actually available. We’ll do that my calling evaluatePolicy: on our context. If this is successful, the Touch ID check can go ahead. If not, we can either ignore it or implement something like a password check instead (I’ve only implemented a log message here).

If the check is successful we can do the actual authentication, using the same method. The parameter for checking is an enumeration with the awesome name LAPolicyDeviceOwnerAuthenticationWithBiometrics (biometrics being the fingerprint part of the context – perhaps when Apple release devices with retina scanners, face detection or DNA verification we’ll have other values here).

// authenticate the user
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:reason reply:^(BOOL success, NSError * _Nullable error) {
            
    // it worked!
    if (success) {
    NSLog(@"Successfully authenticated the user via Touch ID. HUZZAH!");
    } else {
    NSLog(@"Could not authenticate the user via Touch ID. \nReason: %@ \nError Code: %ld", error.localizedDescription, error.code);
                
    // if the user chooses the password option
    if (error.code == -3) {
        // handle password input here
        NSLog(@"Let's ask for your password instead");
        }
    }
}];

Note that there is one other value in this enumeration called LAPolicyDeviceOwnerAuthentication. Don’t use that: although it’s available, and it brings up the lock screen’s familiar passcode entry view, it’s throwing an exception when I tried to use it. I’ve not found anything in the Apple documentation on this value, although Xcode does suggest it as part of code completion. Anyway, moving on…

It’s a long method that takes a completion block (reply), inside which we handle the authentication. If the Touch ID is not successful, iOS automatically brings up an additional option that asks for a password.

Screen Shot 2015-09-23 at 15.58.32

To handle a user pressing that option, we’ll check for the error.code property: if it’s -3, it means that the user has selected the Fallback Mechanism. We’ll handle it here. Handle other error codes here too if you like and let the user know what’s going on and why.

And that’s it! Everything else is handled by iOS.

Testing

You can test this code on Touch ID devices (iPhone 5s, iPad Air 2, etc) as well as on the simulator. By default Touch ID will be disabled. Enable it by heading over to Hardware – Touch ID Enrolled.

To trigger a correct or failed finger touch use the appropriate option under

Hardware – Simulate Finger Touch

.

Screen Shot 2015-09-23 at 16.28.04

Demo Project and Documentation

Here’s a demo project on GitHub that shows this code in action:

Here’s Apple’s official documentation about Touch ID:





Leave a Reply