EllipticCurveKeyPair icon indicating copy to clipboard operation
EllipticCurveKeyPair copied to clipboard

Dismiss TouchID authentication

Open Vabs28 opened this issue 8 years ago • 13 comments

Hi

I am not sure if this is possible. Can we cancel TouchID authentication happening on decrypt operation if we dont want to proceed? LAContext has a method "invalidate" which invalidates LAContext and throws LAErrorAppCancel error.

e.g. We prompt user to authenticate using TouchID as soon as app is opened. We also make a background call to check if user is running on latest app. If user is running on old version then we cancel TouchID operation and show a message which says "Please update app to latest version."

Vabs28 avatar Oct 03 '17 07:10 Vabs28

I’m really not sure. https://youtu.be/fpaQpyU_QiM

hfossli avatar Oct 03 '17 07:10 hfossli

Why do you want to cancel? What is the use case?

hfossli avatar Oct 03 '17 07:10 hfossli

e.g. We prompt the user to authenticate using TouchID as soon as the app is opened. The app may also receive some authentication messages that he needs to action (select Accept/Reject on 2FA messages).

If the app receives an Authentication messages then we cancel the TouchID operation and show the authentication message.

Vabs28 avatar Oct 03 '17 07:10 Vabs28

I have rewritten some of the code so I'm now able to pass a LAContext to sign and decrypt. Sad thing is that I don't get to dismiss the LAContext once it is showing the fingerprint dialog. Do you know how?

Example

import UIKit
import LocalAuthentication

class ViewController: UIViewController {

    var context: LAContext! = LAContext()
    
    func createAccessControl(protection: CFString = kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flags: SecAccessControlCreateFlags = [.userPresence, .privateKeyUsage]) -> SecAccessControl {
        var error: Unmanaged<CFError>?
        let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, flags, &error)
        return accessControl!
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        delay(1.0, queue: .main) {
            self.decrypt()
        }
    }
    
    func decrypt() {
        
        let accessControl = createAccessControl()
        context.evaluateAccessControl(accessControl, operation: .useKeySign, localizedReason: "Sign") { (success, error) in
            DispatchQueue.main.async {
                if success {
                    let alert = UIAlertController(title: "Authenticated", message: "Ready to sign/decrypt", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
                    self.show(alert, sender: nil)
                } else {
                    let alert = UIAlertController(title: "Failed to authenticate", message: "Error: \(error!)", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
                    self.show(alert, sender: nil)
                }
            }
        }
        
        delay(3.0, queue: .main) {
            self.context.invalidate()
        }
    }
}

func delay( _ delay: Double, queue: DispatchQueue, completion: @escaping () -> () ) {
    queue.asyncAfter(deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
        completion()
    }
}

It doesn't seem promising.

hfossli avatar Oct 04 '17 09:10 hfossli

If you are able to remove the dialog then I'll be happy to finish the rewrite to support LAContext.

hfossli avatar Oct 04 '17 09:10 hfossli

Hi I am new to Swift development. I also tried similar thing, it doesn't close TouchID dialog. Rather calling invalidate method doesn't do anything, you can still authenticate yourself with correct fingerprint.

Vabs28 avatar Oct 04 '17 12:10 Vabs28

So then I guess this is not possible... sadly. If you find a way to close it I’ll be more than happy to change the library

hfossli avatar Oct 04 '17 13:10 hfossli

I have pushed my code to master. Whenever you sign or decrypt you will have the possibility of passing a LAContext.

Like this

let signature = try manager.sign(digest, authenticationContext: context)

hfossli avatar Oct 19 '17 08:10 hfossli

In this archive you'll find two files and you'll see there's a bug with LAContext

Bug.zip

hfossli avatar Oct 19 '17 08:10 hfossli

Thanks a lot

Vabs28 avatar Oct 21 '17 22:10 Vabs28

http://www.openradar.me/35069937

hfossli avatar Nov 10 '17 08:11 hfossli

Apple thinks this is fixed in latest GM. Are you, @Vabs28, able to check this? img_0331

hfossli avatar Dec 12 '17 21:12 hfossli

It seems apple solved this when working with the LAContext directly. It doesn't work for me when the LAContext is presented by Security framework for some reason.

hfossli avatar May 07 '18 14:05 hfossli