I have a SIMPLE login screen and I am protecting against missing data as follows:
#IBAction func btnLoginTapped(_ sender: Any)
{
guard let email = emailTextField.text, !email.isEmpty else
{
self.showMessage(messageToDisplay: "Email Address is required", title: "")
return
}
guard let password = passwordTextField.text, !password.isEmpty else
{
self.showMessage(messageToDisplay: "Password is required", title: "")
return
}
....
I load the app on my device and press login and get the alert "Email Address is required". I enter my email address and press login and get the alert "Email Address is required" and NOT "Password is required"
How can that be???
If there's a problem with the first guard let, we print "Email Address is required" and return.
Thus, the second guard let is never encountered and "Password is required" is never printed.
Your code will never print both messages; that would be impossible, the way you've written the code.
So we have to conclude that one of the tests in the first guard let is failing. But you have not given enough information for us to know why that is. Perhaps emailTextField is nil? Perhaps showMessage doesn't do what you think it does? You could be making a lot of wrong assumptions here. But the logic of your code is clear.
Related
I thought I'd return to StackOverflow with another question because you guys helped me significantly with my last issue
Anyway, I currently have my authentication system setup so that the sign in and signup button are shared. I am looking to have firebase reference storage when an email is entered to have it checked against other accounts in the database. As of right now, a user can enter an email address for their account and then if they enter the wrong password it just sends them right to the sign up even though they currently have an account. This is a serious problem as it will cause confusion
I want it to work like so:
If the email address is taken, I want an alert to be displayed for the user says "Incorrect password"
If the email address is not taken, I want it to tell the user that they need to enter a password with at least 10 characters, 1 number, and 1 special character, which I have already figured out using
I only want it to segue to create a new user if the email is not taken and the password and email field meet the criteria fields that I have already set within my code. I just need help preventing it from switching to the create new user VC if the email is already taken, and I need to to say
func isValidPassword(_ email: String) -> Bool {
let emailRegEx = "##$%^&+=^.*(?=.{10,})(?=.*d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##$%^&+=]).*$"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: email)
}
Anyway, here is the code so far attached to the IBAction
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password, completion:
{ (user,error) in
if error == nil {
if let user = user {
self.userUid = user.user.uid
self.goToFeedVC()
}
} else {
self.goToCreateUserVC()
Here is a picture of the interface
I want it to be intuitive but I have been unable to code this myself so if anyone is able to help advise me on how to finish this block it would be incredibly appreciated
Firebase gives pretty detailed error responses for their Auth call:
So you can check to see what the error is inside of your call:
Below are the two error that they give (I only added the two scenarios that you mentioned)
Description: The password is invalid or the user does not have a password.
FIRAuthErrorUserInfoNameKey: ERROR_WRONG_PASSWORD
&
There is no user record corresponding to this identifier. The user may have been deleted.
FIRAuthErrorUserInfoNameKey: ERROR_USER_NOT_FOUND
Auth.auth().signIn(withEmail: email, password: password, completion:
{ (user,error) in
if error == nil {
if let user = user {
self.userUid = user.user.uid
self.goToFeedVC()
}
} else {
guard let error = error?.localizedDescription else { return } // but actually handle this
print(error)
if error == wrong password {
// show alert for email taken/wrong password
} else if error == user doesnt exists {
// self.goToCreateUserVC()
}
}
}
Just replace the if and else if conditions with the actual errors. I'd avoid comparing the strings and use the key/code in case the strings change in the future.
Official list of error codes can be found here
And if you print the full error instead of the error?.localizedDescription you'll get the full details, as can be seen here:
Optional(Error Domain=FIRAuthErrorDomain Code=17011 "There is no user record corresponding to this identifier. The user may have been deleted." UserInfo={NSLocalizedDescription=There is no user record corresponding to this identifier. The user may have been deleted., FIRAuthErrorUserInfoNameKey=ERROR_USER_NOT_FOUND})
Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!)
{ (user, error) in
if error != nil {
print(error!)
self.warningLabel.isHidden = false;
self.passwordTextField.text = "";
} else {
print("Log in succesful")
self.performSegue(withIdentifier: "welcomeSeg", sender: self)
}
}
Whenever I sign in or sign up a user I just print a generic warning label instead of the actual issue. I print the error I receive and it's too verbose to show to the user.
Error Domain=FIRAuthErrorDomain Code=17009 "The password is invalid or the user does not have a password." UserInfo={NSLocalizedDescription=The password is invalid or the user does not have a password., error_name=ERROR_WRONG_PASSWORD}
Error Domain=FIRAuthErrorDomain Code=17008 "The email address is badly formatted." UserInfo={NSLocalizedDescription=The email address is badly formatted., error_name=ERROR_INVALID_EMAIL}
Is there any way to fetch the error code so I can be more specific with my error messages? I've looked through the documentation but have been unsuccessful in coming up with anything.
I would recommend creating an AuthErrorCode object (provided by the Firebase SDK) from the error you receive and using that as you see fit. If I remember correctly, AuthErrorCode is an enum with cases like .wrongPassword, .invalidEmail, etc.
A simple pseudocode example:
if error != nil {
if let error = AuthErrorCode(rawValue: error?.code) {
switch error {
case .wrongPassword:
// do some stuff with the error code
}
}
Also, I feel your pain. I've found that the Swift SDK documentation lags quite a bit when changes come along.
I am making my own app in Swift, and wanted to include the feature of resetting passwords using Parse. My console eventually shows a successful notice, but when I go to the email to see if Parse sent the email to reset password, I don't receive anything. Would really appreciate it if you could help me sort this issue :D I've added a screenshot so that you can see what my console shows.
#IBAction func recoverPasswordButton(_ sender: Any) {
PFUser.requestPasswordResetForEmail(inBackground: emailTextField.text!, block: { (success, error) in
if self.emailTextField != nil {
self.displayAlert(title: "Check your email", message: "A link has been sent to recover your password. Follow the instructions.")
print("A link to recover your password has been sent")
} else {
var errorText = "Unknown error: please try again"
if let error = error {
errorText = error.localizedDescription
}
self.displayAlert(title: "Email is not valid", message: errorText)
}
})
}
For Email verification, You need to add the setting in the dashboard like below
The first thing is that Parse stops his support, you have to use Back4App.
I just started working with servers in swift and I'm using parse server hosted by AWS to store a database of users when they create an account for my app. I have this function called sign up that is linked to a sign up button which works fine and properly stores user's info into my parse database.:
#IBAction func signUp(_ sender: AnyObject) {
//I first check to see if the users left any of the fields blank
if firstName.text == "" || lastName.text == "" || email.text == "" || userName.text == "" || password.text == "" {
createAlert(title: "Error in form", message: "Please fill in all text fields")
//If everything is filled in
}else{
let user = PFUser()
user.username = userName.text
user["firstname"] = firstName.text
user["lastname"] = lastName.text
user.email = email.text
user.password = password.text
user.signUpInBackground(block: { (success, error) in
if error != nil {
var displayErrorMessage = "Please try again later."
if let errorMessage = (error! as NSError).userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Signup error", message: displayErrorMessage)
}else{
print("User signed up")
}
})
}
}
Now i need help storing this code on the cloud.
The reason why I ask this is because I had previously posted a question a little different on stack overflow: Deleting PFUser objects from database in swift
And in the response, I was told to store this exact function in cloud code (rather than locally) and I don't know how to do that.
Can anyone show me how it's done?
Thanks a lot in advance!
I'm assuming what it means when you want to "store your code in the cloud" is that all personal info (name, email, password) should be handled from the backend, not that you actually store the code in the cloud. You should handle sensitive personal data from the server-side and not the client-side. This involves server-side encryption and handling requests with SSL exchanges. This is beyond the scope of my expertise and this question, and I highly encourage that you do more research before you try to tackle this problem in your app. Here are some links I found:
http://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html
https://www.raywenderlich.com/92667/securing-ios-data-keychain-touch-id-1password
What they told you is to implement that code in the server, the server should be the one to process the function you ask for in the past question, this one, I think you have already done it because you said the info is stored successfully, but what the answer above this says is that to implement that code in an actual app you should investigate more about security and encryption to protect users information.
I have a UItextField called addUserField in which a user can enter an email after the user hits enter I am checking if that email exists in my Firebase DB and if it does it must print "OK"\email and if does not then it should print "BAD"\email. However my code below is not doing what its intended to, it is somehow executing the if conditions twice and I am not able to figure out why.
So incase the email exists in the database it is printing:
OK xyz#abc.com
BAD xyz#abc.com
Incase the email does not exist in the database it is printing:
BAD abc#xyz.com
BAD abc#xyz.com
Can anybody help me figure out why the if statement is executing twice and how can I make it so that it just print OK if email exists or BAD if it does not.
func textFieldShouldReturn(_textField: UITextField!) -> Bool {
var email: String = ""
if let userEmail = addUserField.text{
email = userEmail
}
let userRef = ref.child("users");
userRef.queryOrderedByChild("role").queryEqualToValue("User").observeEventType(.Value, withBlock: {
snapshot in
for child in snapshot.children {
let username = child.value["email"] as! String
if (email == username){
print ("OK \(email)")
}
else {
print ("BAD \(email)")
}
}
})
return true
}