7

I want to take different actions to users if device support Face ID or Touch ID.

When using the Face ID, iOS asking permission to use. (unlike Touch ID).

And if the user denies permission, context.biometryType return LABiometryTypeNone.

Is there anyway to check Touch ID or Face ID supported by device.

LAContext *context = [[LAContext alloc] init];

NSError *error;

if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {

}

if (@available(iOS 11.0, *)) {
    if (context.biometryType == LABiometryTypeFaceID) {
        // support FaceID 
    }
}

// support TouchID

Console output

(lldb) po error
Error Domain=com.apple.LocalAuthentication Code=-6 "User has denied the use of biometry for this app." UserInfo={NSLocalizedDescription=User has denied the use of biometry for this app.}

(lldb) po context.biometryType
LABiometryTypeNone

NOTE: I Don't want to use passcode authentication. I just need to know device is support Touch ID or Face ID

3 Answers3

1

Use property biometryType of LAContext to check and evaluate available biometric policy. (For a passcode authentication , when biometric fails, use: LAPolicyDeviceOwnerAuthentication)

Try this and see:

LAContext *laContext = [[LAContext alloc] init];

NSError *error;


// For a passcode authentication , when biometric fails, use: LAPolicyDeviceOwnerAuthentication
//if ([laContext canEvaluatePolicy: LAPolicyDeviceOwnerAuthentication error:&error]) {
if ([laContext canEvaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {    
    if (error != NULL) {
        // handle error
    } else {

        if (@available(iOS 11, *)) {
            if (laContext.biometryType == LABiometryTypeFaceID) {
                //localizedReason = "Unlock using Face ID"
                NSLog(@"FaceId support");
            } else if (laContext.biometryType == LABiometryTypeTouchID) {
                //localizedReason = "Unlock using Touch ID"
                NSLog(@"TouchId support");
            } else {
                //localizedReason = "Unlock using Application Passcode"
                NSLog(@"No biometric support or Denied biometric support");
            }
        } else {
            // Fallback on earlier versions
        }


        [laContext evaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"Test Reason" reply:^(BOOL success, NSError * _Nullable error) {

            if (error != NULL) {
                // handle error
            } else if (success) {
                // handle success response
            } else {
                // handle false response
            }
        }];
    }
}
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • As I mention that, if the user denied to use Face ID, biometryType returns LABiometryTypeNone. So I can't take appropriate action. You can see the console output. – Furkan yeşiloğlu Jan 22 '18 at 14:04
  • Yes, ofcourse, when user has denied, it will automatically show `Passcode` screen. – Krunal Jan 22 '18 at 14:05
  • For a passcode authentication , if biometric fails, use: LAPolicyDeviceOwnerAuthentication – Krunal Jan 22 '18 at 14:08
  • Yes I know that, It will not help to my question. I just need to know device is support Touch ID or Face ID. – Furkan yeşiloğlu Jan 22 '18 at 14:14
  • `LAPolicyDeviceOwnerAuthentication` gives you result for all, just try with my code and see. If use has denied permission then if will fall into error bloack. Else it will give you available biometry type (either face-id or touch-id) for iOS 11. Note: for iOS 10 and below, there is/was not face-id support. – Krunal Jan 22 '18 at 14:16
  • And if you want to check with biometry only then try with `LAPolicyDeviceOwnerAuthentication` only. Execute code and see result. – Krunal Jan 22 '18 at 14:17
1

No. If the user denies the Privacy Permissions prompt with the NSFaceIDUsageDescription, all future instances of LAContext will have a biometryType property of .none once canEvalutePolicy:error: is called on them.

markedwardmurray
  • 523
  • 4
  • 10
1

It's too late but I hope this can help whoever have the same issue.

LAContext().canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) LAContext().canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)

the difference between deviceOwnerAuthentication & deviceOwnerAuthenticationWithBiometrics that the first one will tell you the device have authentication method or not .. second one have same behavior but only works is user accepted the permission.

enum BiometryResult: Int {
case faceID
case touchID
case notExist
}
class func biometryType() -> BiometryResult {
    let context = LAContext()
    if (context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)) {
        if (context.biometryType == LABiometryType.faceID) {
            return .faceID
        } else if (context.biometryType == LABiometryType.touchID) {
            return .touchID
        } else {
            return .notExist
        }
    }
    return .notExist
}
Mohammed Gomaa
  • 91
  • 2
  • 11