Refactoring: Face ID/Touch ID for iOS 13 Update

Back in February 2015, my article on Touch ID was published on raywenderlich.com. I was written in Swift for Xcode 8. Every year or so i would update the article as an author on the iOS Team. Here’s a link to the latest — How To Secure iOS User Data: The Keychain and Biometrics – Face ID or Touch ID. A few months ago, I had to update one of my own apps for iOS 13 with Apple’s biometric identification framework, Local Authentication. My app was also still supporting Objective-C so here’s follow up on what I had to change. As a bonus you can also take your user to Settings in case they have disabled

First thing is to add Local Authentication at the top of the Login view controller.


#import <LocalAuthentication/LocalAuthentication.h>

Next create an action for the Touch ID method:

- (IBAction)touchIDAction:(id)sender {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;

NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app";
//...
}

After that we need to check if the device can support biometrics with canEvaluatePolicy and have an error ready.

Inside the touchIDAction add:

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
error:&authError]) {
// 1. successful steps
} else {
// 2. Oops. There's a error!
}

Inside the canEvaluatePolicy, we’ll use evaluatePolicy:localizedReason:reply. The reply will have a block that either succeeds or fails with our error.

// 1. successful steps.
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates

// using a Keychain utility method to get the email and password
NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil];
self->passwordTextField.text = passwordFound;
self->usingSecureID = true; // a Bool I added to keep track
[self loginAction:nil];
[NSLog showWithStatus:@"Logging_In"];
});
});
} else {
// User did not authenticate successfully, look at error and take appropriate action

//I'm using a showAlert method to bring up a UIAlertViewController
[self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"];
return;
}
}];

What do we do if there is an error enabling Face ID/Touch ID? It could be because the user has disabled the feature. What’s new is that we can now take the user to your application settings — without a hack.

Initially you can pop up an alert to inform the user. Added to UIKit in iOS 8, UIApplicationOpenSettingsURLString lets you add a button to the alert that will take the user to your app in Settings, where they can enable Face ID/Touch ID.

// Could not evaluate policy; look at authError and present an appropriate message to user
NSString *title = @"Error!";
  NSString *message = @"Your device cannot authenticate using TouchID.";
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
// do we need to return animation?
                                                          }];
    // open your app in Settings
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    UIApplication *application = [UIApplication sharedApplication];
    NSString *settingTitle = @"Settings";
    UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault
                                                           handler:^(UIAlertAction * action) {
                                                             [application openURL:url  options:@{}
completionHandler:nil];
                                                           }];
    [alert addAction:settingsAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
    return;
}

The whole method would look like this:

- (IBAction)touchIDAction:(id)sender {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;

NSString *myLocalizedReasonString = @"Used for quick and secure access to the test app";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
// 1. successful steps

[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates

// using a Keychain utility method to get the email and password
NSString *passwordFound = [KeychainUtils getPasswordForUsername:self->emailTextField.text andServiceName:@"My_app" error:nil];
self->passwordTextField.text = passwordFound;
self->usingSecureID = true; // a Bool I added to keep track
[self loginAction:nil];
[NSLog showWithStatus:@"Logging_In"];
});
});
} else {
// User did not authenticate successfully, look at error and take appropriate action

//I'm using a showAlert method to bring up a UIAlertViewController
[self showAlert: @"There was a problem verifying your identity." withTitle:@"Error!"];
return;
}
}];
} else {
// 2. Oops. There's a error!

// Could not evaluate policy; look at authError and present an appropriate message to user
NSString *title = @"Error!";
  NSString *message = @"Your device cannot authenticate using TouchID.";
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
// do we need to return animation?
                                                          }];
    // open your app in Settings
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    UIApplication *application = [UIApplication sharedApplication];
    NSString *settingTitle = @"Settings";
    UIAlertAction* settingsAction = [UIAlertAction actionWithTitle:settingTitle style:UIAlertActionStyleDefault
                                                           handler:^(UIAlertAction * action) {
                                                             [application openURL:url  options:@{}
completionHandler:nil];
                                                           }];
    [alert addAction:settingsAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
    return;
}
}
}

Episode 226 – Bendgate Pro

This week Greg Heo leads the crew as they discuss the Windows 95 ugly holiday sweater, NHL hockey overtime 3 on 3, and protocol conformance. We follow up on Apple shutting down Music’s Connect feature, Sega Genesis Classics are playable on Amazon Fire, the C64 Mini, Windows Sandbox, Apple is producing new Peanuts content, breaking into Amazon face recognition with 3D printed heads, T-Mobile eSIM support, Apple will allow IAP gifted to Friends & Family. Apple will build new campus in Austin and add jobs across the US. Cydia Store shuts down. Apple confirms some iPad Pros ship slightly bent, but says it’s normal. Picks: Xcode Comment-Spell-Checker, 6 Audio books on Apple Books, The 8-Bit Guy, Functional Swift 2018 videos, MagazineLayout

Episode 226 Show Links:

Episode 226 Picks:

Episode 222 – Everyone’s A Publisher

We follow up on folding phones as Google adds support to Android. Apple cuts production on all new iPhone X series phones. Verizon will bring eSIM support for iPhones. Amazon US will now sell Macs for Apple. Prince William weighs in on social network giants lack of discretion. Tim Cook says regulations as inevitable. Apple has bought a privacy-conscious AI start up. Picks: Swift Heroes 2018 conference videos, Mini vMac for iOS, Deep Learning Specialization

Episode 222 Show Links:

Episode 222 Picks:

Episode 219 – Acquisitions and Murders

Microsoft has bought GItHub. IBM is buying Red Hat. Apple bars Bloomberg from iPad event. All of the Apple Logos Included in the October 30 Event. Tim Mitra Blends Art and (Computer) Science at TD Bank. JAMF – There is no step three. New 2018 MacBook Air, 2018 Mac Mini, 2018 iPad Pro – 11” & 12.9”, and 2nd Gen. Apple Pencil. Picks: Designing for iPad Pro and Apple Pencil, Bringing Your Apps to iPad Pro, Shared Version Number trick

Episode 219 Show Links

Episode 219 Picks

Episode 218 – Golfing With the Blue Jays

We follow up on not using Facebook for logins and Apple and AWS request the Bloomberg retract the Chinese Spy Chip story. Apple is working on a patch for the #Beautygate — where the iPhone XS is over beautifying portrait photos. We revisit Swift & Objective-C usage. The October 30th event will apparently introduce 2 new iPad Pros, iPad Mini, two iMacs and possibly a new MacBook. IBM open sources their Mac@IBM configuration. Tim Cook calls for strong US Privacy legislation. We touch on the upcoming 5G mobile service. Picks: Xcode 10 patches to Advanced Apple Debugging & Reverse Engineering, Hawkeye Access.

Episode 218 Show Links:

Episode 218 Picks:

Episode 172 – Peggy Bundy Style

This week we are joined by Greg Heo as we discuss Apple’s latest security bug. We discuss migrating to Swift 4. Our #askMTJC topics are dissecting AirPlane Mode’s Animoji based music video, and whether Face ID will be used by advertisers. We follow up on Uber’s coverup of user data hacks and how it happened. Apple has published the iTunes holiday shutdown schedule. Apple has released fixes for the critical macOS High Sierra security issue. *The Apple Forum post we discuss on the show has been unpublished. Amazon’s Reinvent conference has released a number of things; Amazon Sumarian has online 3D tools. Picks: NEHotspotConfiguration, Egg Freckles – a Newton styled blog, Apple Support channel on YouTube, iOS Conf Singapore videos.

Episode 172 Show Links:

Episode 172 Picks:

Episode 171 – A Fiduciary Duty

We begin our US Thanksgiving Episode looking into the iPhone’s density from our #askMTJC as well as Reachability. iOS 11 has some layout bugs. The HomePod will be delayed until the new year. Fact Check: Face ID does learn from its mistakes, also you need to focus on it sometimes. Tim shares some experiences updating apps for the iPhone X. The iPhone SE may get updated in the new year. We ponder that Swift code will run on Google’s Fuchsia OS. iOS 11.2 will allow introductory subscription pricing. We discuss the issues around Net Neutrality as the FCC votes on it. We discuss Uber’s attempt to cover up a major hack where 57 million user accounts are stolen. Coding can be done at the same time with Atom’s Teletype and Visual Studio’s Live Share. Picks: iOS Thanksgiving 2017: Tools & Libraries We’re Thankful For, Optimize Swift Build Times, Avoiding force unwrapping in Swift unit tests, Skydio is hiring: iOS Engineer, Android Engineer, Mobile QA Engineer

Sponsor: RayWenderlich.com – Black Friday Sale

Episode 171 Links:

Episode 171 Picks:

Episode 170 – Not Fully Formed

We follow up on macOS Server Mac app, blockchain on tracking pot Marajuana distribution, unlocking Face ID, Lyft coming to Canada, and iOS hardware encryption. Also hackers say they broke Face ID, a 10-year old can unlock his mom’s iPhone X, and we take a deep look at the iPhone X portrait mode. Picks: Much ado about iOS app architecture, SBSAnimoji, Power Photos and, Computer Science Distilled

Episode 170 Show Links:

Episode 170 Picks:

Episode 166 – Geez. I Don’t Know

This week Mark and Tim give #askMTJC advice on updating Xcode 9 and it’s benefits. They also discuss the FreeDOS project. Tim discusses Mike Ash’s suggestion of wiping the iPhone 6 Plus and reinstalling iOS 11. iPhone X devices start to ship out in advance of new orders. KRAK is a new WPA2 exploit that affects all users and is being patched. Senator Al Franken queries Apple about Face ID and privacy. Picks: Xcode Main Thread Checker, Three Finger Drag, iTune 12.6.3

Thanks Gord!

Episode 166 Show Links:

Episode 166 Picks:

Episode 163 – The Coefficient of Friction Is µ

We follow up on the Chevy Nova story. We debate Tim’s iPhone 7 Plus and iPhone 8 Plus, phone back’s friction coefficient throw down. We follow up on Apple’s former GPU maker Imagination sale, the cost of building an iPhone 8 and Dyson is building electric cars. We discuss the FaceID Security Guide and Amazon’s hardware event. Picks: Monster Truck AR, JSON to Swift, TypeScript, Go, C#, Java, and more :: quicktype.

Episode 163 Show Links:

Episode 163 Picks: