2

I have an app where the user can authenticate either with TouchID / FaceID (if Available, enrolled and enabled) or with passcode. All those options can be set in the settings of the app and are stored in UserDefaults. Once the app loads, it checks if those Bool keys have true value in UserDefaults and act accordingly.

My problem comes when a user has a device with TouchID/FaceID but they haven't enabled & enrolled it. In this case, the app should show passcode screen only. But instead, I'm presented by TouchID on my iPhone, when I have disabled the option (for testing purposes). According to Apple's documentation, it says:

If Touch ID or Face ID is available, enrolled, and not disabled, the user is asked for that first. Otherwise, they are asked to enter the device passcode.

On a simulator, I see the Passcode screen, but on my iPhone, I see the TouchID pop up when it's disabled and UserDefaults returns false for that key. Why is that happening? What am I doing wrong?

override func viewDidLoad() {
   super.viewDidLoad()
   setUI()
}

 func setUI() {
    let faceTouchIdState = UserDefaults.standard.bool(forKey: DefaultsKeys.faceTouchIdState)
    let passcodeState    = UserDefaults.standard.bool(forKey: DefaultsKeys.passcodeState)

    if faceTouchIdState {
       print("Authenticate")
       authenticate()
    }
    else {
       print("Passscode")
       showEnterPasscode()
    }
}

func showEnterPasscode() {
    let context = LAContext()
    var errMess: NSError?
    let policy = LAPolicy.deviceOwnerAuthentication

    if context.canEvaluatePolicy(policy, error: &errMess) {
        context.evaluatePolicy(policy, localizedReason: "Please authenticate to unlock the app.") { [unowned self] (success, err) in
        DispatchQueue.main.async {
            if success && err == nil {
               self.performSegue(withIdentifier: "GoToTabbar", sender: nil)
            }
            else {
                 print(err?.localizedDescription)
            }
           }
        }
    }
    else {
        print("cannot evaluate")
    }
}
Dani
  • 3,427
  • 3
  • 28
  • 54

1 Answers1

1

There is nothing wrong with your code. I believe the issue is on how you did this "I have disabled the option (for testing purposes)".

Since you were prompted with the "Touch ID" pop up, then it proves that your biometric wasn't really disabled. I surmise that you toggled one of the "USE TOUCH ID FOR" switches and thought doing so will disable biometric in your app, which it won't.

If you want to test the fallback to passcode in your device:

  • try unenrolling all fingerprints

OR

  • disable your fingerprint via inputting unenrolled fingerprints on your app multiple times.
  • 1
    Oh, I didn't know that. Your assumption that i toggled the "Use touch ID" was right. I'd test your suggestions. Thank you, that helps a lot – Dani May 08 '19 at 09:04
  • 1
    You're welcome. Comment here if you finally solved it. Thanks – Joshua Francis Roman May 08 '19 at 09:09
  • 1
    I just removed all fingerprints and tested it again, now it shows the Passcode screen. You were indeed right. This was the problem. Toggling off the TouchID certainly doesn't mean that it's disabled as I thought. Once again, thank you. – Dani May 08 '19 at 09:15