How to show enter password and try again alert view - swift

So I want to make a touchid authentication but if the touchid does not match there will be an alert to enter the password and try again
I am using XCode 9.0.0
#IBAction func ac(_ sender: Any) {
let context:LAContext=LAContext()
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil){
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "use your touch id", reply: {(wasCorrect,error) in
if wasCorrect {
print("correct")
}else{
print("incorrect")
}
})
}else{
}
}

The best way (from the users point of view) would be to enable / show a "Re-Authenticate" button if the authentication fails. Then, the user has to actively tap that button to re-run the autentication loop.
If you would automatically start re-authentication instead, the user might get annoyed by autentication dialogs popping up all the time, wich also might look a little weired because sometimes the animations overlap and the screen seems to flicker.

this will work, updated for swift 3 and 4
func authenticationWithTouchID() {
let localAuthenticationContext = LAContext()
localAuthenticationContext.localizedFallbackTitle = "Use Passcode"
var authError: NSError?
let reasonString = "To access the secure data"
if localAuthenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
localAuthenticationContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString) { success, evaluateError in
if success {
//TODO: User authenticated successfully, take appropriate action
} else {
//TODO: User did not authenticate successfully, look at error and take appropriate action
guard let error = evaluateError else {
return
}
let message = self.evaluateAuthenticationPolicyMessageForLA(errorCode: error._code)
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
} else {
guard let error = authError else {
return
}
let message = self.evaluateAuthenticationPolicyMessageForLA(errorCode: error._code)
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
and methods to get the error messages
func evaluatePolicyFailErrorMessageForLA(errorCode: Int) -> String {
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:
message = "Authentication could not continue because the user has been locked out of biometric authentication, due to failing authentication too many times."
case LAError.biometryNotEnrolled.rawValue:
message = "Authentication could not start because the user has not enrolled in biometric authentication."
default:
message = "Did not find error code on LAError object"
}
} else {
switch errorCode {
case LAError.touchIDLockout.rawValue:
message = "Too many failed attempts."
case LAError.touchIDNotAvailable.rawValue:
message = "TouchID is not available on the device"
case LAError.touchIDNotEnrolled.rawValue:
message = "TouchID is not enrolled on the device"
default:
message = "Did not find error code on LAError object"
}
}
return message;
}
func evaluateAuthenticationPolicyMessageForLA(errorCode: Int) -> String {
var message = ""
switch errorCode {
case LAError.authenticationFailed.rawValue:
message = "The user failed to provide valid credentials"
case LAError.appCancel.rawValue:
message = "Authentication was cancelled by application"
case LAError.invalidContext.rawValue:
message = "The context is invalid"
case LAError.notInteractive.rawValue:
message = "Not interactive"
case LAError.passcodeNotSet.rawValue:
message = "Passcode is not set on the device"
case LAError.systemCancel.rawValue:
message = "Authentication was cancelled by the system"
case LAError.userCancel.rawValue:
message = "The user did cancel"
case LAError.userFallback.rawValue:
message = "The user chose to use the fallback"
default:
message = evaluatePolicyFailErrorMessageForLA(errorCode: errorCode)
}
return message
}

Hope this will help:
func authenticateUser() {
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 {
self.runSecretCode()
} 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)
}
}
For more understanding: https://www.hackingwithswift.com/example-code/system/how-to-use-touch-id-to-authenticate-users-by-fingerprint

#IBAction func ac(_ sender: Any) {
let context:LAContext=LAContext()
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil){
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "use your touch id", reply: {(wasCorrect,error) in
if wasCorrect {
}else{
let myalert = UIAlertController(title: " Password Title", message: "Message ", preferredStyle: UIAlertControllerStyle.alert)
myalert.addAction(UIAlertAction(title: "Retry", style: .default) { (action:UIAlertAction!) in
print("retry")
})
self.present(myalert, animated: true)
}
})
}else{
// If You Wanna Show Alert
let myalert = UIAlertController(title: "Title", message: "Message ", preferredStyle: UIAlertControllerStyle.alert)
myalert.addAction(UIAlertAction(title: "Retry", style: .default) { (action:UIAlertAction!) in
print("retry")
})
self.present(myalert, animated: true)
}
}

Related

PARSE user still active after log-out

I'm learning to use Parse Server to manage users and passwords. I have an app that lets the user log-in and store information in the server (age, weight, gender and name). But I'm having a problem, if the user logs out, the app takes them to the login page and, if after that they use a non-existing user or incorrect password, after showing the alert "Incorrect user or password", the app takes them to the main page with the previous user information. I'm not sure what is going on; the code I'm using to log in is this:
#IBAction func signInButton(_ sender: Any) {
let acl = PFACL()
acl.getPublicWriteAccess = true
PFUser().acl = acl
if userTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error", message: "Both fields should be filled")
} else {
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
PFUser.logInWithUsername(inBackground: userTextField.text!, password: passwordTextField.text!, block: { (user, error) in
self.activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
if error != nil {
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Login Error", message: displayErrorMessage)
} else {
print("Logged in")
let usuario = PFUser.current()
let dataUse = self.queryDownload(usuario: usuario!)
for items in dataUse {
let dataMeassure: GlucoseEvents = NSEntityDescription.insertNewObject(forEntityName: "GlucoseEvents", into: DatabaseController.getContext()) as! GlucoseEvents
dataMeassure.allAtributes = items
}
DatabaseController.saveContext()
self.performSegue(withIdentifier: "goToMain", sender: self)
}
})
}
}
Now, this problem only happens after the logout, so I'm guessing the error in that function. The code of the logout is:
#IBAction func logOut(_ sender: Any) {
let refreshAlert = UIAlertController(title: "Confirm", message: "Really LogOut?", preferredStyle: UIAlertControllerStyle.alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
PFUser.logOutInBackground { (error) in
if error != nil {
self.createAlert(title: "Error", message: "Error")
}
}
self.performSegue(withIdentifier: "closedProf", sender: self)
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
print("Handle Cancel Logic here")
}))
present(refreshAlert, animated: true, completion: nil)
}
Is there another way to logout and avoid this problem? Thanks
More info
So I tried to see if the problem was the server not returning a nil user. And added a print statement to the logout. Turns out that it's nil so I don't know why it is being stored (or where) but the LogOut returns a nil user.

iOS Firebase: Retrieve and match database code to pass through authentication

I'm trying to create an authentication security code for admin to login/ register. What I wish to do is login to perform segue if the user pass through the code which exists in firebase database. So now it doesn't works as Error alert box keep popping out event I have enter the correct security code.
let alertController = UIAlertController(title: "Security Code?", message: "Please enter your dedicated security code", preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "Next", style: .default) { (_) in
let code = alertController.textFields?[0].text
let scref=Database.database().reference();
scref.queryOrdered(byChild: "securitycode").queryEqual(toValue: code).observe(.value, with: { (snapshot) in
if (snapshot.exists())
{
Auth.auth().signIn(withEmail: self.emailText.text!, password: self.passwordText.text!, completion: { (user, error) in
if user != nil
{
//if sign in sucessful
self.performSegue(withIdentifier: "segueadmin", sender: self)
} else
{
if let myError = error?.localizedDescription{
print(myError)
let alertController = UIAlertController(title: "Error!", message: myError, preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default) {
UIAlertAction in
// Insert code to run on button click below
self.printYes()
})
self.present(alertController, animated: true, completion: nil)
}else{
print("ERROR")
}
}
})}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
alertController.addTextField { (textField) in
textField.placeholder = "Enter Code:"
}
//adding the action to dialogbox
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
//finally presenting the dialog box
self.present(alertController, animated: true, completion: nil)
}
}
I think it might be an issue when you query your database.
Try this code :
scref.child("securitycode").child(code).observe(.value, with: { (snapshot) in
if (snapshot.exists()) {
...//Do your thing
}
With this your aim the reference /securitycode/{code} and if it exists it seems that there is a correct value stored in your database so you can proceed. If not the user can't proceed.
Oops! Very careless of me! It because of I didn't structure the data well and forgot to put " " for the data in Firebase.
So the firebase database should be:
And the code shall be:
ref=Database.database().reference().child("securitycode")
ref.queryOrdered(byChild: "code")
.queryEqual(toValue: self.textf.text)
.observe(DataEventType.value, with: { (snapshot) in

AWS Cognito: Trying to Alert User of Error

I am having difficulty in capturing a Cognito Sign Up Error. I am trying to alert the user when Cognito returns a "UsernameExistsException","message":"User already exists" Error.
Below is my code:
self.pool!.signUp(usernameTextField.text!, password: passwordTextField.text!, userAttributes: attributes, validationData: nil).continue(successBlock: { (task:AWSTask!) in
// needs to be async so we can ALWAYS return nil for AWSTask
DispatchQueue.main.async {
if task.error != nil { // some sort of error
let myerror = task.error
print("\(myerror)")
let alert = UIAlertController(title: "Sign Up Error", message: (task.error?.localizedDescription)! as String, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
else {
let response: AWSCognitoIdentityUserPoolSignUpResponse = task.result! as AWSCognitoIdentityUserPoolSignUpResponse
// NSLog("AWSCognitoIdentityUserPoolSignUpResponse: \(response)")
self.user = response.user
let alert = UIAlertController(title: "Sign Up Successful", message: "", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { action in self.performSegue(withIdentifier: "confrimationSegue", sender: self) }))
self.present(alert, animated: true, completion: nil)
}
}
return nil
})
For some reason am unable to break into the task.error != nil conditional statement. When I force an error the error does not print and alert action does not present to the view. Am I attempting to alert the user in the wrong function? How else can I check for the Username Already Exists error presented by cognito. Thanks in advance.
You are using a successBlock, which means that the block that you set is only going to be called when the sign up was performed succesfully. That's why the error is always nil.
In order to have the error, you should set the callback simply by something like the following:
userPool
.signUp(user.email, password: user.password, userAttributes: attributes, validationData: nil)
.continue({ response in
if let error = response.error {
// Error ocurred
} else {
// No error ocurred
})
This continue method only recieves the callback and will be called when a error happens.

Firebase error handling while creating user Swift

I am currently developing an iOS application and I wanted to implement the Firebase database.
I'm facing an issue while handling errors during the users creation process. I always get the default error from the switch, here is my code :
FIRAuth.auth()?.createUser(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in
if (error != nil) {
if let errCode = FIRAuthErrorCode(rawValue: error!._code) {
var alertController = UIAlertController(title: "", message: "", preferredStyle: UIAlertControllerStyle.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
(result: UIAlertAction) -> Void in
print("Error transmitted")
}
switch errCode {
case .errorCodeInvalidEmail:
print("Invalid email")
alertController = UIAlertController(title: "Error", message: "Email syntax is not correct", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(okButton)
self.present(alertController, animated: true, completion: nil)
case .errorCodeEmailAlreadyInUse:
print("Email already in use")
alertController = UIAlertController(title: "Error", message: "This email is already in use", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(okButton)
self.present(alertController, animated: true, completion: nil)
case .errorCodeWeakPassword:
print("Password weak")
alertController = UIAlertController(title: "Error", message: "Password is too weak. Please choose a password which contains at least 6 characters.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(okButton)
self.present(alertController, animated: true, completion: nil)
default:
// ALWAYS GET HERE.
print(error)
alertController = UIAlertController(title: "Error", message: "An unknown error occured.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(okButton)
self.present(alertController, animated: true, completion: nil)
}
}
} else {
print("User created")
let newUser = ["email": self.emailField.text!]
let firebaseNewUser = self.ref.childByAutoId()
firebaseNewUser.setValue(newUser)
}
Moreover, the print(error) displays :
Optional(Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred,
print and inspect the error details for more information."
UserInfo={NSUnderlyingError=0x170257be0 {
Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)"
UserInfo={FIRAuthErrorUserInfoDeserializedResponseKey={
code = 400;
errors = (
{
domain = usageLimits;
message = "Bad Request";
reason = keyExpired;
}
);
message = "Bad Request";
}}},
error_name=ERROR_INTERNAL_ERROR,
NSLocalizedDescription=An internal error has occurred, print and inspect the
error details for more information.})
Can someone help me please ?
Try enabling identity toolkit API in google console.
Actually, (in answer to the previous message), the identity toolkit API was already activated.
The problem was coming from the fact that an API key was generated but was restrained to websites requests.
Solution : So I just generated another API key, restrained it to iOS applications, downloaded the .plist once again, put it into the project and add the API_KEY in it (API_KEY as an information property and the value as the new generated api key value)
For Created New User Please follow this simple code . Please put this code in Create Button #IBAction function.
FIRAuth.auth()?.createUserWithEmail(Username.text!, password: Password.text!
, completion: {
user , error in
if error != nil {
print("Something Went to Wrong :(")
}
else {
print("Account Created Sucessfully ")
}
})

Duplicate email Alert Swift + Parse

I'm trying to have it so when a user creates an account... if their email hasn't been used before an Alert box appears saying "Account created" and if the email is already in created (on Parse) then an alert should appear notifying the user.
I can't seem to get my code to do both..only display one message. What am I doing wrong here?
Thanks!
func createNewUser() {
let newUser = PFUser()
newUser.email = emailSignUp.text
newUser.username = emailSignUp.text
newUser.password = passwordSignUp.text
newUser.signUpInBackgroundWithBlock { ( success: Bool, error: NSError?) -> Void in
if newUser.username != nil {
let alert: UIAlertController = UIAlertController(title: "Account created", message: "Please confirm your email", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default) { action -> Void in
}
alert.addAction(okButton)
self.presentViewController(alert, animated: true, completion: nil)
}
else {
let alert: UIAlertController = UIAlertController(title: "Email already registered", message: "Please enter a different email", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
alert.addAction(okButton)
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
If memory serves the error that's returned if a user already exists is a different string than a generic error. You can try to match the error string and then display an alert if it matches or a different one if it's just an error (like the error string itself).
newUser.signUpInBackgroundWithBlock { ( success: Bool, error: NSError?) -> Void in
if error != nil {
if let errorString = error.userInfo?[“error”] as? String {
if errorString == “username \(emailSignUp.text) already taken” {
// Create alert that address is taken
} else {
// Create other case alert, though it may make sense to just display the error string in an alert box
}
}
} else {
// Do your usual stuff
}