First and foremost I am very new to swift, and it is not my primary language. I have some difficulty to understand the concurrent constructs, and some are not yet available (until macOs 12 is released).
So I'd like the command line app to use the touchId of the laptop to access some data. I found numerous examples of the LAContext.evaluatePolicy
call. However they seem all related to GUI apps (either in macOs or on iOS).
My problem is that I am working on a terminal app and the evaluatePolicy
is evaluate on a private queue while the main thread finishes without leaving the time to actually show the authentication dialog.
I've tried to create a very simple reproducer, purely in swift. (But my terminal app has some code in C that calls the swift method).
import LocalAuthentication
@_cdecl("authenticate")
public func authenticateUser() {
let context = LAContext()
context.localizedFallbackTitle = "Please use your password"
context.localizedCancelTitle = "Abort"
var authorizationError: NSError?
let permissions = context.canEvaluatePolicy(
LAPolicy.deviceOwnerAuthentication, // TouchId or passcode
error: &authorizationError
)
if permissions {
let biometry = context.biometryType
if (biometry != LABiometryType.touchID) {
print("TouchID not available")
return
}
let reason = "Identify yourself!"
print(reason)
context.evaluatePolicy(
LAPolicy.deviceOwnerAuthentication,
localizedReason: reason
) { (success: Bool, error: Error?) -> Void in
if success {
print(" You may enter")
} else {
print(" Authentication failed")
print(error?.localizedDescription ?? "Failed to authenticate")
}
}
// <-------- block here
} else {
let ac = "Touch ID not available, Or Your device is not configured for Touch ID."
print(ac)
}
}
authenticateUser()
In this code snippet, I'd like the code to block to wait on the evaluatePolicy
result. Via its reply completion handler or else.
I have tried to use DispatchQueue.main.async
but this doesn't work, so I ultimately didn't do it correctly. Also I have tried using await/async, but swiftc
tells me those aren't available on my system (concurrency is only available in macOS 12.0.0 or newer
).
This can be compiled and executed this way:
$ swiftc main.swift
$ ./main
Identify yourself!
Thanks in advance for pointers to make this work.
Some versions
$ swiftc --version
Apple Swift version 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
Target: x86_64-apple-darwin20.6.0
$ sw_vers
ProductName: macOS
ProductVersion: 11.6
BuildVersion: 20G165