iOS fingerprint identification login process and Implementation

Keywords: iOS github git Swift

Change from: Ren Bo'an Brief Book

Chatting

Recently, I've been chasing after Qingyun Zhi. I always feel that TV plays are not as wonderful as novels. Yes, the acting skills of the big cafes are amazing and the adaptation of the plot is compact, but it has to be said that many things can not be achieved by acting alone. The protagonist's heart can only be seen in the novel at every moment. (In order to install X, he bought a bunch of genuine collections at any cost.)

Looked at the children's shoes know that Zhang Xiaofan's hand magic weapon is soul and bloodthirsty beads with Zhang Xiaofan refined blood as a medium. And this magic weapon has a great quality, that is, in addition to the people who are related to Zhang Xiaofan, you can not control it even if you have the ability to master it. Loyalty is so hard to pursue. When we talk about it, we will probably get to the point. Right, this magic weapon has its own security verification function, similar to our password verification and fingerprint identification verification function today.

A Brief Analysis of Fingerprint Recognition

Apple designed iOS with security as its core. Whether it's sandbox mechanism or code signature, their ultimate goal is security.

Since the launch of the iPhone 5S, Apple has launched a new bio-safety identification technology, Touch ID. It enables us to access devices safely faster and more easily. It is valuable that Touch ID can read fingerprint data from any angle and overcome the inconvenience of locking based on password. In addition, Apple has added scenarios where password checking is necessary to further ensure security, such as [1]:
- Just start or restart;
- Over 48 hours without unlocking equipment;
- The device received the remote lock command.
- Five times failed to match fingerprints.
- Enter Touch ID setting module or update new fingerprint;

Most importantly, Apple provides Touch ID for third-party applications, which will only receive notifications of the success of authentication, but will not be able to access Touch ID or data related to registered fingerprints, which is particularly important for security.

In order to achieve higher security, many banking and payment APPs integrate fingerprint, gesture and other secondary verification functions. Today we will focus on the specific process and implementation of integrating Touch ID into APP.

Process analysis

Fingerprint login process:

Recognize login after second boot:

Friends who have used fingerprints to log in probably know the process above.
The difficulty of this business is that the first login is successful and fingerprint authorization is enabled - > after exit from APP - > second start of APP. How to judge whether to enable fingerprint login authentication? At this time, we need to have a deep understanding of data persistence and data sharing. Many APP developers, when developing login retention, mostly use persistent data to store successful logon marks. However, for a more secure APP, the login status is checked every time it restarts, and persistent data alone is not enough.

My solution is:
Maintain login through three data sets.
- loginState: Persistent data, used to store user login success, inactivated state;
- Start AutoLogin State: Persistent data, whether to open fingerprint identification authorization;
- isAppCurrentLoginState: Sharing data, login activation status, which is characterized by the fact that every restart of APP will reinitialize data.

First login:

Three data changes,

state loginState startAutoLoginState isAppCurrentLoginState
Before login nil or NO nil or NO NO
Login successfully YES nil or NO YES
Enable fingerprint authorization YES YES YES
Do not enable authorization YES NO YES
Secondary authentication login (fingerprint login):

Three data changes,
- If loginState and start AutoLoginState are YES, fingerprint login verification can be performed. The following is the data change.

state loginState startAutoLoginState isAppCurrentLoginState
Before verification YES YES NO
Validation failed NO YES NO
Verify success YES YES YES

- Otherwise, login again.

Core Code Implementation

Determine whether the device supports fingerprint recognition

/**
 * Determine whether the device supports fingerprint recognition
 */
- (IBAction)loginBtnAction:(UIButton *)sender
{

    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"loginState"];

    EVNHelper *helper = [EVNHelper shareHelper];
    helper.isAppCurrentLoginState = YES;

    LAContext *context = [[LAContext alloc] init]; // Initialization of context objects
    NSError *error = nil;
    // Determine whether the device supports fingerprint recognition
    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error])
    {
        // Support fingerprint verification
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Log in successfully!" message:@"Whether to Enable Fingerprint Logon" preferredStyle:UIAlertControllerStyleAlert];

        __weak typeof (self) weakSelf = self;

        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Later on" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
            weakSelf.transLoginStateBlock(); // Return
            [self dismissViewControllerAnimated:YES completion:nil];
        }];

        UIAlertAction *startUseAction = [UIAlertAction actionWithTitle:@"Enable" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {

            [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"startAutoLoginState"];
            weakSelf.transLoginStateBlock(); // Return
            [self dismissViewControllerAnimated:YES completion:nil];

        }];
        [alertController addAction:cancelAction];
        [alertController addAction:startUseAction];

        [self presentViewController:alertController animated:YES completion:nil];
    }
    else
    {
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"startAutoLoginState"];
        self.transLoginStateBlock(); // Return
        [self dismissViewControllerAnimated:YES completion:nil];
    }

}

Fingerprint login verification

/**
 * Fingerprint login verification
 */
- (void)loadAuthentication
{
    __weak typeof(self) weakSelf = self;

    LAContext *myContext = [[LAContext alloc] init];
    // This property is the option to set the pop-up box after fingerprint input fails
    myContext.localizedFallbackTitle = @"Forget password";

    NSError *authError = nil;
    NSString *myLocalizedReasonString = @"Please hold down. Home Key completion verification";
    // MARK: Determining whether the device supports fingerprint recognition
    if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError])
    {
        [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:myLocalizedReasonString reply:^(BOOL success, NSError * _Nullable error) {
            if(success)
            {
                NSLog(@"Successful fingerprint authentication");

                weakSelf.helper.isAppCurrentLoginState = YES;

                weakSelf.logoutBtnAction.hidden = NO;
                weakSelf.userInfo.text = @"Ren Bo an";
            }
            else
            {
                weakSelf.helper.isAppCurrentLoginState = NO;
                NSLog(@"Fingerprint authentication failed.%@",error.description);

                NSLog(@"%ld", (long)error.code); // Error code error.code
                switch (error.code)
                {
                    case LAErrorAuthenticationFailed: // Authentication was not successful, because user failed to provide valid credentials
                    {
                        NSLog(@"privilege grant failed"); // - 1 Three consecutive fingerprint identification errors
                    }
                        break;
                    case LAErrorUserCancel: // Authentication was canceled by user (e.g. tapped Cancel button)
                    {
                        NSLog(@"User Cancel Authentication Touch ID"); // - 2 Clicked the Cancel button in the TouchID dialog box

                    }
                        break;
                    case LAErrorUserFallback: // Authentication was canceled, because the user tapped the fallback button (Enter Password)
                    {
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"User chooses to enter password and switch main thread processing"); // - 3 Click the Enter Password button in the TouchID dialog box
                        }];

                    }
                        break;
                    case LAErrorSystemCancel: // Authentication was canceled by system (e.g. another application went to foreground)
                    {
                        NSLog(@"Cancel authorization, such as other application entry, user autonomy"); // - 4 TouchID dialog box is cancelled by the system, such as pressing Home or power button
                    }
                        break;
                    case LAErrorPasscodeNotSet: // Authentication could not start, because passcode is not set on the device.

                    {
                        NSLog(@"No password set in device system"); // -5
                    }
                        break;
                    case LAErrorTouchIDNotAvailable: // Authentication could not start, because Touch ID is not available on the device
                    {
                        NSLog(@"Equipment not set Touch ID"); // -6
                    }
                        break;
                    case LAErrorTouchIDNotEnrolled: // Authentication could not start, because Touch ID has no enrolled fingers
                    {
                        NSLog(@"Users did not enter fingerprints"); // -7
                    }
                        break;

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
                    case LAErrorTouchIDLockout: //Authentication was not successful, because there were too many failed Touch ID attempts and Touch ID is now locked. Passcode is required to unlock Touch ID, e.g. Evaluation of LAPolicy Device Owner Authentication Within Biometrics will ask for passcode as a prerequisite user to repeatedly fail Touch ID authentication, Touch ID is locked, and user input password is required. Unlock, first verify the password with Touch ID
                    {
                        NSLog(@"Touch ID Locked, requiring the user to enter a password to unlock"); // - Five consecutive fingerprint identification errors, TouchID function is locked, the next time you need to enter the system password
                    }
                        break;
                    case LAErrorAppCancel: // Authentication was canceled by application (e.g. invalidate was called while authentication was in progress). If a phone call suddenly came, the phone application entered the front desk and the APP was hung up.
                    {
                        NSLog(@"In case of user uncontrollability APP Hang up"); // -9
                    }
                        break;
                    case LAErrorInvalidContext: // LAContext passed to this call has been previously invalidated.
                    {
                        NSLog(@"LAContext Invalidated before passing to this call"); // -10
                    }
                        break;
#else
#endif
                    default:
                    {
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"In other cases, switch the main thread processing");
                        }];
                        break;
                    }
                }
            }
        }];
    }
    else
    {
        NSLog(@"Device does not support fingerprints");
        NSLog(@"%ld", (long)authError.code);
        weakSelf.helper.isAppCurrentLoginState = NO;
        switch (authError.code)
        {
            case LAErrorTouchIDNotEnrolled:
            {
                NSLog(@"Authentication could not start, because Touch ID has no enrolled fingers");
                break;
            }
            case LAErrorPasscodeNotSet:
            {
                NSLog(@"Authentication could not start, because passcode is not set on the device");
                break;
            }
            default:
            {
                NSLog(@"TouchID not available");
                break;
            }
        }
    }
}

General effect:

Demo GitHub Download Link: EVNTouchIDDemo.git If it's useful, give me a Star...

Reference:
[1]iOS security guide;
[2]Apple Objective-C;
[3]Apple Swift API.

Posted by echoofavalon on Sun, 31 Mar 2019 08:15:29 -0700