1

I am authenticating a user via LAContext when an app is launching or when will enter foreground. If a device was locked then the user will be asked twice to authorize himself. To avoid that behavior, I set context.touchIDAuthenticationAllowableReuseDuration value to 240 but It doesn't work as expected. The user still has to authorize himself twice. What I am doing wrong?


import LocalAuthentication

class AccessControl {

    internal var context = LAContext()
    private var policy: LAPolicy = .deviceOwnerAuthentication
    private var reason: String = NSLocalizedString("auhenticationLocalizedFallbackTitle", comment: "")

    init() {
        context.touchIDAuthenticationAllowableReuseDuration = 240
    }

    func evaluateUserWithBiometricsOrPasscode(success: @escaping () -> Void, error: @escaping () -> Void) {

        guard context.canEvaluatePolicy(policy, error: nil) else {
            error()
            return
        }
        context.evaluatePolicy(policy, localizedReason: reason) { eStatus, eError in
            DispatchQueue.main.async {
                if eStatus {
                    success()
                } else {
                    error()
                }
            }
        }
    }

}
Blazej SLEBODA
  • 8,936
  • 7
  • 53
  • 93

1 Answers1

3

You need to use the same LAContext object everytime to get that behaviour.

class AccessControl {

    // MARK: - Singleton
    public static let shared = AccessControl()

    // Policy
    private var policy: LAPolicy = .deviceOwnerAuthentication

    // Reason
    private var reason: String = NSLocalizedString("auhenticationLocalizedFallbackTitle", comment: "")

    // Context
    lazy var context: LAContext = {
        let mainContext = LAContext()
        if #available(iOS 9.0, *) {
            // specify your interval
            mainContext.touchIDAuthenticationAllowableReuseDuration = 60
        }
        return mainContext
    }()


    // Evaluate
    func evaluateUserWithBiometricsOrPasscode(success: @escaping () -> Void, error: @escaping () -> Void) {

        guard context.canEvaluatePolicy(policy, error: nil) else {
            error()
            return
        }
        context.evaluatePolicy(policy, localizedReason: reason) { eStatus, eError in
            DispatchQueue.main.async {
                if eStatus {
                    success()
                } else {
                    error()
                }
            }
        }
    }
}

And calling this function like below: This will work for FaceID Authentication also.

AccessControl.shared.evaluateUserWithBiometricsOrPasscode(success: {

}) {

}
rushisangani
  • 3,195
  • 2
  • 14
  • 18