1

I've implemented password/TouchID/FaceID on a view controller and when I hit the success case, I'd expect the prompt to stop firing but it just fires over and over again.

In my VC:

var context: LAContext!

func authenticateReturningUser() {
    context = LAContext()
    var error: NSError?

    if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
        let reason = "Verify that this is your device to continue."

        context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
            DispatchQueue.main.sync {
                guard success else {
                    guard let error = error else {
                        // show error
                        return
                    }

                    switch error {
                    case LAError.userCancel:
                        // do stuff
                        return
                    default: return
                    }
                }

                print("success")
            }
        }
    }
}

The prompt should fire once and not again if the user successfully authorizes

Edit:

authenticateReturningUser is called from the AppDelegate's applicationDidBecomeActive function:

self.coverVC?.completionHandler = { self.removeBackgroundVC() }
self.coverVC?.authenticateReturningUser()
Zack Shapiro
  • 6,648
  • 17
  • 83
  • 151

2 Answers2

1

As far as I remember, when showing the Touch ID prompt, your app becomes inactive. So when the prompt is dismissed, your app becomes active again, triggering the App Delegate's applicationDidBecomeActive again.

You might consider introducing a flag that stores whether the app became inactive because of Touch ID / Face ID etc. or because of another reason and use it in applicationDidBecomeActive to decide if authentication should be triggered or not.

Daniel Seither
  • 1,647
  • 1
  • 13
  • 19
0

Where are you calling authenticateReturningUser()? You may want to create a static boolean authenticated that if false, allows the call to authenticateReturningUser(), and if true, skips the call, and set authenticated = true after calling the function once.

MJ31
  • 31
  • 6