touchID implementation error cancelled by user - ios

How to resolve the TouchId error: Domain=com.apple.LocalAuthentication Code=-2 "Canceled by user."
I tried to add local context again:
let myContext = LAContext()
let myLocalizedReasonString = "Please use your last login for Inspyrus Supplier Central."
var authError: NSError?
if #available(iOS 8.0, macOS 10.12.1, *) {
if myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
myContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString) { success, evaluateError in
DispatchQueue.main.async {
if success {
self.btnLoginClicked(UIButton())
} else {
print(evaluateError?.localizedDescription ?? "Failed to authenticate")
// Fall back to a asking for username and password.
// ...
}
}
}
}
}

You can check if the evaluateError returned from the evaluatePolicy call is a LAError.userCancel.
Something like this:
if success {
//...
}
else if let authError = evaluateError as? LAError {
switch authError.code {
case .userCancel:
// Authentication was canceled by user (e.g. tapped Cancel button).
break
default:
// Other error
break
}
// Or
switch authError {
case LAError.userCancel:
// Authentication was canceled by user (e.g. tapped Cancel button).
break
default:
// Other error
break
}
}

Related

Handle if user cancels Facebook-Login in Swift 5

I have an app where the user is able to login with Facebook.
Everything is working fine but I have a problem when the user cancels the login-process. There are two different scenarios that I would like to handle but I have no idea how:
1.
2.
I couldn't find anything no this so I hope someone can help me out here.
This is my handleFBLogin-method which is getting called when the user taps on a button:
//MARK: Facebook Login
#objc func handleFBLogin(){
// disable button tap
self.facebookButton.isEnabled = false
// hide the buttons title
self.facebookButton.setTitle("", for: .normal)
// start loading animation
setupLoadingAnimation()
logoAnimation.play()
let accessToken = AccessToken.current
LoginManager().logIn(permissions: ["email", "public_profile"], from: self) { (result, error) in
if error != nil {
// stop loading animation
self.logoAnimation.stop()
// remove animation from view
self.logoAnimation.removeFromSuperview()
// reset button title to "Registrieren"
self.facebookButton.setTitle("Mit Facebook fortfahren", for: .normal)
// play shake animation
self.facebookButton.shake()
// enable button tap
self.facebookButton.isEnabled = true
// some FB error
Utilities.showErrorPopUp(labelContent: "Fehler beim Facebook-Login", description: error!.localizedDescription)
return
}
// successfull FB-Login
GraphRequest(graphPath: "/me", parameters: ["fields": "id, email, name"]).start { (connection, result, error) in
if error != nil {
// stop loading animation
self.logoAnimation.stop()
// remove animation from view
self.logoAnimation.removeFromSuperview()
// reset button title to "Registrieren"
self.facebookButton.setTitle("Mit Facebook fortfahren", for: .normal)
// play shake animation
self.facebookButton.shake()
// enable button tap
self.facebookButton.isEnabled = true
// some FB error
Utilities.showErrorPopUp(labelContent: "Fehler beim Facebook-Login", description: error!.localizedDescription)
}else {
print(result!)
// check if user has account
guard let Info = result as? [String: Any] else { return }
let email = Info["email"] as? String
Auth.auth().fetchSignInMethods(forEmail: email!) { (methods, error) in
if error != nil {
// stop loading animation
self.logoAnimation.stop()
// remove animation from view
self.logoAnimation.removeFromSuperview()
// reset button title to "Registrieren"
self.facebookButton.setTitle("Mit Facebook fortfahren", for: .normal)
// play shake animation
self.facebookButton.shake()
// enable button tap
self.facebookButton.isEnabled = true
// show error popUp
Utilities.showErrorPopUp(labelContent: "Fehler", description: error!.localizedDescription)
} else {
// no error -> check email adress
// Email ist noch nicht registriert -> sign up
if methods == nil {
let usernameVC = self.storyboard?.instantiateViewController(withIdentifier: "UsernameVC") as! UserNameVC
usernameVC.accessToken = accessToken
self.navigationController?.pushViewController(usernameVC, animated: true)
}
// Email ist registriert -> login
else {
// set user status to logged-in
UserDefaults.standard.setIsLoggedIn(value: true)
UserDefaults.standard.synchronize()
// stop animation
self.logoAnimation.stop()
// transition to Home-ViewController
self.transitionToHome()
}
}
}
}
}
}
}
You need to handle 3 cases
if error != nil {
print("Facebook login failed. Error \(error)")
} else if result?.isCancelled == true {
print("Facebook login was cancelled.")
} else {
// clicked ok go on
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if ((error) != nil) {
// Process error
}
else if result.isCancelled {
// Handle cancellations
}
else {
// Navigate to other view
}
}

How to get a callback every time faceid/touchid authentication fails

We have a requirement where we have to block the user for 24 hours if Face ID or Touch ID fails for 5 consecutive time.
In Face ID, I am using the fallback to call authentication manager again, and after total of 6 attempts (2 in each call), I block the user in the fallback method itself.
In Touch ID, on third failure, I get a call back to Authentication failed. I call authentication manager again, and on 5th try, I get a call back to Lockout in which I can block the user.
Is there any way common in both Face ID and Touch ID where I can get a callback after every single individual failure so that I can block the user on 5th failure itself?
//MARK:- Check if user has valid biometry, if yes, validate, else, show error
fileprivate func biometricAuthentication(completion: #escaping ((Bool) -> ())){
// addBlurredBackground()
//Check if device have Biometric sensor
if biometryRetryCount == 2 {
authenticationContext.localizedFallbackTitle = "Ok"
} else {
authenticationContext.localizedFallbackTitle = "Retry"
}
let isValidSensor : Bool = authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
if isValidSensor {
//Device have BiometricSensor
authenticationContext.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: biometryRetryCount == 2 ? "You have been blocked from using the application for next 24 hours. Please come back later" : "Touch / Face ID authentication",
reply: { [unowned self] (success, error) -> Void in
if(success) {
// Touch or Face ID recognized
// self.removeBlurredBackground()
completion(true)
} else {
//If not recognized then
if let error = error {
let msgAndAction = self.errorMessage(errorCode: error._code)
if msgAndAction.0 != "" {
UIApplication.topViewController()?.showAlert(withTitle: "Error", andMessage: msgAndAction.0, andActions: msgAndAction.1)
}
}
completion(false)
}
})
} else {
let msgAndAction = self.errorMessage(errorCode: (error?._code)!)
if msgAndAction.0 != ""{
UIApplication.topViewController()?.showAlert(withTitle: "Error", andMessage: msgAndAction.0, andActions: msgAndAction.1)
}
}
}
The error methods:
//MARK: TouchID error
fileprivate func errorMessage(errorCode:Int) -> (strMessage: String, action: [UIAlertAction]){
var strMessage = ""
let cancelAction = UIAlertAction.init(title: Const.Localize.Common().kCancel, style: .cancel) { (cancelAction) in
}
var actions: [UIAlertAction] = [cancelAction]
switch errorCode {
case LAError.Code.authenticationFailed.rawValue:
biometricAuthentication { (success) in
//
}
case LAError.Code.userCancel.rawValue:
if biometryRetryCount == 2 {
blockUserFor24Hours()
} else {
showAlertOnCancelTapAction()
}
case LAError.Code.passcodeNotSet.rawValue:
strMessage = "Please goto the Settings & Turn On Passcode"
case LAError.Code.userFallback.rawValue:
biometryRetryCount -= 2
if biometryRetryCount == 0 {
blockUserFor24Hours()
} else {
biometricAuthentication { (success) in
//
}
}
default:
strMessage = evaluatePolicyFailErrorMessageForLA(errorCode: errorCode).strMessage
actions = evaluatePolicyFailErrorMessageForLA(errorCode: errorCode).action
}
return (strMessage, actions)
}
func evaluatePolicyFailErrorMessageForLA(errorCode: Int) -> (strMessage: String, action: [UIAlertAction]){
let cancelAction = UIAlertAction.init(title: Const.Localize.Common().kCancel, style: .cancel) { (cancelAction) in
}
var actions: [UIAlertAction] = [cancelAction]
var message = ""
if #available(iOS 11.0, macOS 10.13, *) {
switch errorCode {
case LAError.biometryNotAvailable.rawValue:
message = "Authentication could not start because the device does not support biometric authentication."
case LAError.biometryLockout.rawValue:
showPasscodeScreen()
case LAError.biometryNotEnrolled.rawValue:
message = "You do not have a registered biometric authentication. Kindly go to the settings and setup one"
let settingsAction = UIAlertAction.init(title: Const.Localize.Common().kSetting, style: .default) { (settingsAction) in
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
}
actions.append(settingsAction)
default:
message = "Did not find error code on LAError object"
}
} else {
switch errorCode {
case LAError.touchIDLockout.rawValue:
showPasscodeScreen()
case LAError.touchIDNotAvailable.rawValue:
message = "TouchID is not available on the device"
case LAError.touchIDNotEnrolled.rawValue:
message = "You do not have a registered biometric authentication. Kindly go to the settings and setup one"
let settingsAction = UIAlertAction.init(title: Const.Localize.Common().kSetting, style: .default) { (settingsAction) in
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
}
actions.append(settingsAction)
default:
message = "Did not find error code on LAError object"
}
}
return (message, actions)
}

iOS Customize Local Authentication with Touch ID

I am using the following code to implement the touchID/passcode authentication in my app
let context : LAContext = LAContext()
var error: NSError?
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthentication, error: &error) {
context.evaluatePolicy(LAPolicy.deviceOwnerAuthentication,
localizedReason: messageString,
reply: { (success: Bool, evalPolicyError: Error?) -> Void in
if success {
// ...
}
else {
switch evalPolicyError!._code {
case LAError.systemCancel.rawValue:
print("Authentication was cancelled by the system")
case LAError.userCancel.rawValue:
print("Authentication was cancelled by the user")
case LAError.userFallback.rawValue:
print("User selected to enter custom password")
OperationQueue.main.addOperation({ () -> Void in
// ...
})
default:
print("Authentication failed")
OperationQueue.main.addOperation({ () -> Void in
// ...
})
}
}
})
}
Is is possible to customize it? For example:
Choose the number of TouchID attempts before switching to passcode?
In the first AlertView let user choose to switch to passcode with a button (in the current implementation you can access the passcode only if you fail the TouchID auth)

LAContext canEvaluatePolicy and Swift 2

This is my code in Swift:
if (LAContext().canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics)) {
return true;
}
With Swift2 I changed my code to look like this:
if #available(iOS 8, *) {
if (LAContext().canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics)) {
return true;
}
}
But I get the following error:
Call can throw, but it is not marked with 'try' and the error is not handled
What Am I doing wrong?
You need to do something like this:
do {
try laContext.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics)
// Call evaluatePolicy here
} catch {
print("Cannot evaluate policy, error: \(error)")
}
All methods that returned a Bool and had an inout NSError? as the last parameter were automatically converted (Swift 2) to throw the error, so the parameter was removed. Also the Bool was redundant because it was equal to whether the inout NSError? is nil
EDIT: To get more information about the error use this within the catch:
switch LAError(rawValue: error.code)! {
case .AuthenticationFailed:
break
case .UserCancel:
break
case .UserFallback:
break
case .SystemCancel:
break
case .PasscodeNotSet:
break
case .TouchIDNotEnrolled:
break
default:
break
}
(You can look at all the possible errors by CMD clicking on LAError
EDIT: In XCode 7 beta 5/6 this method doesn't throw anymore, but takes an NSErrorPointer as the last parameter (as does NSURL's checkResourceIsReachableAndReturnError for reasons not known to me). You can however extend your LAContext to make a throwing method like before if you like:
extension LAContext {
func canEvaluatePolicyThrowing(policy: LAPolicy) throws {
var error : NSError?
canEvaluatePolicy(policy, error: &error)
if let error = error { throw error }
}
}
Try this code:
do {
try touchIDContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics)
//Comprobar la repuesta de esa autentificacion
touchIDContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: mensaje, reply: { (success, ErrorType) -> Void in
if success
{
// Autentificacion correcta
alert.title = "Genial!"
alert.message = "Te has autentificado correctamente"
// Mostramos este Alerview
self.presentViewController(alert, animated: true, completion: nil)
}
else
{
//AUTENTIFICACION FALLIDA
//PASAMOS VALORES AL ALERTVIEW
alert.title = "AUTENTIFICACION FALLIDA!!"
//OFRECEMOS MAS INFORMACION SOBRE EL FALLO DE AUTENTIFICAICON
switch ErrorType!.code {
case LAError.UserCancel.rawValue: alert.message = "Usuario Cancela"
case LAError.AuthenticationFailed.rawValue: alert.message = "Autentificacion Fallida!"
case LAError.PasscodeNotSet.rawValue: alert.message = "Password no configurado"
case LAError.SystemCancel.rawValue: alert.message = "Error de sistema"
case LAError.UserFallback.rawValue:alert.message = "Usuario selecciona contrasen"
default:alert.message = "Imposible Autentificarse"
}
//Mostramos el AlertView
self.presentViewController(alert, animated: true, completion: nil)
}
}) // cierre del clousure
} // cierre del do
catch {
print("Cannot evaluate policy, error: \(error)")
} // cierre del catch
For Swift 3, I do this:
context.evaluatePolicy(policy, localizedReason: ...) { (success: Bool, error: Error?) in
DispatchQueue.main.async {
if success {
...
} else if let error = error as? LAError {
switch error.code {
case LAError.authenticationFailed:
...
}
}
}
}

How to use Touch ID sensor in iOS 8

One of the most things I was excited about iOS 8 was the ability to use fingerprint sensors on the iPhone 5s and later. Unfortunately I cannot find out what is the required framework for that, nor how I can make authentication. Please help me with:
What framework required for using Touch ID?
How to use its methods and how to authenticate the user?
A code sample would be much appreciated.
More complete snippet, swift style:
func authenticateUser() {
// Get the local authentication context.
let context = LAContext()
// Declare a NSError variable.
var error: NSError?
// Set the reason string that will appear on the authentication alert.
var reasonString = "Authentication is needed to access your notes."
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
[context .evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
if success {
}
else{
// If authentication failed then show a message to the console with a short description.
// In case that the error is a user fallback, then show the password alert view.
println(evalPolicyError?.localizedDescription)
switch evalPolicyError!.code {
case LAError.SystemCancel.toRaw():
println("Authentication was cancelled by the system")
case LAError.UserCancel.toRaw():
println("Authentication was cancelled by the user")
case LAError.UserFallback.toRaw():
println("User selected to enter custom password")
self.showPasswordAlert()
default:
println("Authentication failed")
self.showPasswordAlert()
}
}
})]
}
else{
// If the security policy cannot be evaluated then show a short message depending on the error.
switch error!.code{
case LAError.TouchIDNotEnrolled.toRaw():
println("TouchID is not enrolled")
case LAError.PasscodeNotSet.toRaw():
println("A passcode has not been set")
default:
// The LAError.TouchIDNotAvailable case.
println("TouchID not available")
}
// Optionally the error description can be displayed on the console.
println(error?.localizedDescription)
// Show the custom alert view to allow users to enter the password.
self.showPasswordAlert()
}
}
Source
The Local Authentication framework provides facilities for requesting authentication from users using Touch ID, following code snipped shows how you should request for authentication.
Objective C
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myReasonString = #"String explaining why app needs authentication";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myReasonString
reply:^(BOOL succes, NSError *error) {
if (success) {
// User authenticated successfully
} else {
// Authenticate failed
}
}];
} else {
// Could not evaluate policy; check authError
}
Swift
let myContext = LAContext()
var authError: NSError?
// Set the reason string that will appear on the authentication alert.
var myReasonString = "String explaining why app needs authentication"
if myContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &authError) {
[myContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myReasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
if success {
// User authenticated successfully
} else {
// Authenticate failed
}
})]
} else{
// Could not evaluate policy; check authError
}
You're looking for LocalAuthentication framework (login may be required to see).
Basically you're interested in LAContext class and its
canEvaluatePolicy:error: and
evaluatePolicy:localizedReason:reply: methods.
The canEvaluatePolicy:error: method is used to check if TouchID authentication is available for you to use.
And use evaluatePolicy:localizedReason:reply: to perform actual authentication check
I was looking for an answer in objectiveC with all the possible errors. Didn't find on this post so here it is.
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = #"Authenticate using your finger";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"User is authenticated successfully");
} else {
switch (error.code) {
case LAErrorAuthenticationFailed:
NSLog(#"Authentication Failed");
break;
case LAErrorUserCancel:
NSLog(#"User pressed Cancel button");
break;
case LAErrorUserFallback:
NSLog(#"User pressed Enter Password");
break;
case LAErrorPasscodeNotSet:
NSLog(#"Passcode Not Set");
break;
case LAErrorTouchIDNotAvailable:
NSLog(#"Touch ID not available");
break;
case LAErrorTouchIDNotEnrolled:
NSLog(#"Touch ID not Enrolled or configured");
break;
default:
NSLog(#"Touch ID is not configured");
break;
}
NSLog(#"Authentication Fails");
}
}];
} else {
NSLog(#"Can not evaluate Touch ID. This device doesn’t support one");
}
Also make sure to use dispatch_async otherwise your uialert messages will not pop-up on time. See sample code below
-(void)viewWillAppear:(BOOL)animated {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = #"Touch ID Test to show Touch ID working in a custom app";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"Success" sender:nil];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.description
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alertView show];
// Rather than show a UIAlert here, use the error to determine if you should push to a keypad for PIN entry.
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:authError.description
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alertView show];
// Rather than show a UIAlert here, use the error to determine if you should push to a keypad for PIN entry.
});
}
}
Swift 3 version of #txulu response:
public func authenticateUser() {
// Get the local authentication context.
let context = LAContext()
// Declare a NSError variable.
var error: NSError?
// Set the reason string that will appear on the authentication alert.
var reasonString = "Authentication is needed to access your notes."
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error) {
[context .evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
if success {
// TODO - Guardar credencials
}
else{
// If authentication failed then show a message to the console with a short description.
// In case that the error is a user fallback, then show the password alert view.
print(evalPolicyError?.localizedDescription)
switch evalPolicyError!.code {
case LAError.systemCancel.rawValue:
print("Authentication was cancelled by the system")
case LAError.userCancel.rawValue:
print("Authentication was cancelled by the user")
case LAError.userFallback.rawValue:
print("User selected to enter custom password")
//self.showPasswordAlert()
default:
print("Authentication failed")
//self.showPasswordAlert()
}
}
} as! (Bool, Error?) -> Void)]
}
else{
// If the security policy cannot be evaluated then show a short message depending on the error.
switch error!.code{
case LAError.touchIDNotEnrolled.rawValue:
print("TouchID is not enrolled")
case LAError.passcodeNotSet.rawValue:
print("A passcode has not been set")
default:
// The LAError.TouchIDNotAvailable case.
print("TouchID not available")
}
// Optionally the error description can be displayed on the console.
print(error?.localizedDescription)
// Show the custom alert view to allow users to enter the password.
//self.showPasswordAlert()
}
}
Full Swift 5 version example snippet:
import LocalAuthentication
_
func authenticateUser() {
// Get the local authentication context.
let context = LAContext()
// Declare a NSError variable.
var error: NSError?
// Set the reason string that will appear on the authentication alert.
let reasonString = "Authentication is needed to provide access."
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error) {
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: Error?) -> Void in
if success {
print("Authentication successful! :) ")
} else {
// If authentication failed then show a message to the console with a short description.
// In case that the error is a user fallback, then show the password alert view.
print(evalPolicyError?.localizedDescription)
switch evalPolicyError!._code {
case LAError.authenticationFailed.rawValue:
print("### Authentication was cancelled by the system")
case LAError.userCancel.rawValue:
print("### Authentication was cancelled by the user")
case LAError.userFallback.rawValue:
print("### User selected to enter custom password")
self.showPasswordAlert()
default:
print("### Authentication failed")
self.showPasswordAlert()
}
}
})
} else {
// If the security policy cannot be evaluated then show a short message depending on the error.
switch error!.code{
case LAError.biometryNotEnrolled.rawValue:
print("### TouchID is not enrolled")
case LAError.passcodeNotSet.rawValue:
print("### A passcode has not been set")
default:
// The LAError.TouchIDNotAvailable case.
print("### TouchID not available")
}
// Optionally the error description can be displayed on the console.
print(error?.localizedDescription)
// Show the custom alert view to allow users to enter the password.
self.showPasswordAlert()
}
}
func showPasswordAlert() {
print("### showPasswordAlert")
}
Among these answers I was getting stuck every time I was running the authentication code.
Please make sure you Import LocalAuthentication to use LAContext and privacy check
With Swift 5 this is what worked for me.
import UIKit
import LocalAuthentication
class ViewController: UIViewController {
#IBOutlet weak var lbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func checkUserAuthentication(_ sender: Any) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[unowned self] success, authenticationError in
DispatchQueue.main.async {
if success {
//Authentication Success
self.lbl.text = "Great!! you are authorised"
} else {
let ac = UIAlertController(title: "Authentication failed", message: "Sorry!", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)
}
}
}
} else {
let ac = UIAlertController(title: "Touch ID not available", message: "Your device is not configured for Touch ID.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
}

Resources