I am trying to login to my user after updating firebase, and after tracing the error, I get the following error:
Error Domain=FIRAuthErrorDomain Code=17007 "The email address is
already in use by another account."
UserInfo={NSLocalizedDescription=The email address is already in use
by another account., error_name=ERROR_EMAIL_ALREADY_IN_USE}
After looking it seems to be a because that firebase user is already in use, I am not sure how to fix this. I believe it is because I never signed out the user before closing app, but not am unable to login as any of my users.
Below is my code:
#IBAction func Login(sender: AnyObject) {
let email = self._Email.text!
let password = self._Password.text!
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error == nil {
//successfull login
print("Successful login****************************************")
//performs a segue to the next view controller
if user!.isEmailVerified{
//if the email is verified
let vc = self.storyboard!.instantiateViewController(withIdentifier: "ProfileView") as! ProfileView
self.present(vc, animated: true, completion: nil)
}
else {
print("email is not verified")
}
} else {
print("Some login error")
}
}
}
As ZassX pointed out, you're indeed using the signUp method of the Firebase iOS SDK, which is the createUserWithEmail. Use this method instead to signIn using email and password:
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
// ...
}
More info: https://firebase.google.com/docs/auth/ios/password-auth
You can check the list of your registered users in your Firebase Authentication Dashboard (https://console.firebase.google.com)
Also, it is good to print out the error description if you're having an error object. Like so:
print(error.localizedDescription).
Related
Question: How do I get the google sign-in page every time user signs-in after signing out?
Issue: Once user signs in for the first time (google sign in pops up) and once the user signs in for the second time. (the google sign in page doesn't pop up) and signs in the user w/o signing in again with their user Google credentials (eg. email, password)
Google Sign-out Button Function
// Sign user out of main application
#IBAction func signOutButtonDidTouch(_ sender: Any) {
// Firebase user authentication fuction
let firebaseAuth = FIRAuth.auth()
if firebaseAuth?.currentUser != nil {
// If there is a user signed-in
do {
try firebaseAuth?.signOut()
print("[Google] signing out successful")
if firebaseAuth?.currentUser == nil {
// Performs current view controller transition to SignInViewController
performSegue(withIdentifier: "signOutSegue", sender: self)
}
}catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
print("[Google] signing out error")
}
}
You sign out of Firebase Auth, but you're still signed in with Google (there is a token in the keychain on the device). If you sign out of the Google account as well, that should address it:
GIDSignIn.sharedInstance().signOut()
Firebase Auth treats Google as just another identity provider, as with Facebook or Twitter, so it doesn't tweak the state of that when the Firebase Auth state changes.
I have same problem. Firstly I can login with email and password.
Then I can signing with google successfully.
After that, I tried to logout from Google again.
When I re-authenticaite with email and password, this message is returned: "The password is invalid or the user does not have a password."
On Firebase console, the users account symbol change from mail to Google.
I couldn't solve this problem. What is my wrong?
In AppDelegate.swift:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
log.debug("Error Google Sign-in: \(error)")
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
if let error = error {
log.error(error)
return
}
// User is signed in
}
}
This is the logout button action:
#IBAction func logout_TouchUpInside(_ sender: Any) {
do {
try Auth.auth().signOut()
GIDSignIn.sharedInstance().signOut()
} catch let error {
self.writeReport(string: error.localizedDescription)
log.error(error.localizedDescription)
self.showAlert(title: "Error", message: error.localizedDescription)
}
log.info("After logout current user: \(String(describing: Auth.auth().currentUser))")
}
I am doing project on secured authentication....when i try to register my email id and password it is not going to next viewcontroller...when i run my code it is working well and not showing any errors but i am not getting output...here is my code
#IBAction func signInButtonTapped(_ sender: UIButton) {
// TODO: Do some form validation on the email and password
if let email = emailTextField.text, let pass = passwordTextField.text {
// Check if it's sign in or register
if isSignIn {
// Sign in the user with Firebase
FIRAuth.auth()?.signIn(withEmail: email, password: pass, completion: { (user, error) in
// Check that user isn't nil
if let u = user {
// User is found, go to home screen
self.performSegue(withIdentifier: "goToHome", sender: self)
}
else {
// Error: check error and show message
self.displayAlertMessage(messageToDisplay: "Password didn't match");
}
})
}
else {
// Register the user with Firebase
FIRAuth.auth()?.createUser(withEmail: email, password: pass, completion: { (user, error) in
// Check that user isn't nil
if let u = user {
// User is found, go to home screen
self.performSegue(withIdentifier: "goToEnroll", sender: self)
}
else {
// Error: check error and show message
}
})
}
}
Please check the connection in Storyboard, make sure that the segue name of link between Current VC -> Home VC is: "goToHome"
Check the same for Enroll VC
Check here if the idenfier is same as you have given in your story board.
Note: Please check first that the identifier you have mentioned here is same as your storyboard one.
Currently I'm working with a Firebase authentication and handled many errors like wrong username, password, empty fields etc and everything is working fine. However when I try to add a segue to the next page and use random email which is not exist in the database, Firebase auth didn't give me any errors and just pass the user to the next page. When I remove the segue and put random user it gives me an error that could not find such user which is what I'm trying to achieve with the segue. Please advise, what might be the problem?
AuthService file
func login(email: String, password: String, onComplete: Completion?) {
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
self.handleFirebaseError(error: error! as NSError, onComplete: onComplete)
} else {
onComplete?(nil, user)
}
})
}
func handleFirebaseError(error: NSError, onComplete: Completion?) {
print(error.debugDescription)
if let errorCode = FIRAuthErrorCode(rawValue: error.code) {
switch (errorCode) {
case .errorCodeInvalidEmail:
onComplete?("Invalid email address", nil)
break
case .errorCodeWrongPassword:
onComplete?("Invalid password", nil)
break
case .errorCodeUserNotFound:
onComplete?("Can't find user", nil)
break
default:
onComplete?("There was a problem authentication. Try again", nil)
}
}
}
ViewController
#IBAction func loginBtnTapped(_ sender: Any) {
if let email = emailField.text, let pass = passwordField.text , (email.characters.count > 0 && pass.characters.count > 0) {
AuthService.instance.login(email: email, password: pass, onComplete: { (errMsg, data) in
guard errMsg == nil else {
self.alert(title: "Error Authentication", errMsg: errMsg!)
return
}
})
} else {
self.alert(title: "Username and password required", errMsg: "You must enter both a username and a password")
}
}
hybridcattt is correct. I'm going to add a more specific answer. When using segues, make sure it the next screen is not directly connected from the button, otherwise it will fire as soon as you tap it, regardless of the result you're waiting for.
Connect your view controller instead to the next view controller, like so:
And then add an indentifier to that segue.
Finally, when you get what you're waiting for (e.g. successful logging in), then do the performSegue.
If you are creating a segue in a storyboard, it fires immediately and opens the next view controller. Login code you have is async, and storyboard doesn't wait for it.
It is very likely that loginBtnTapped method is not even called if you have a segue configured (try adding a breakpoint there)
I tried running the following and it does not work. What am I doing wrong to check the Firebase server if the user has already used the email?
FIRAuth.auth()!.createUser(withEmail: self.userEmailTextField.text!, password: self.userPasswordTextField.text!) {(createUser, error) in
if error != nil {
FIRAuth.auth()!.signIn(withEmail: self.userEmailTextField.text!, password: self.userPasswordTextField.text!)
//Display logged in
let viewController = self.storyboard!.instantiateViewController(withIdentifier: "TabBarController") as UIViewController
self.present(viewController, animated: true, completion: nil)
}else {
//Display an alert message
self.displayMyAlertMessage(userMessage: "Email already in use. Please see the login page.")
return
}
}
Please refer below code.
Code:
FIRAuth.auth()?.createUser(withEmail: email, password: password) {
(user, error) in
if (error) {
// Email is already in use.
} else {
// Create new user successfully
}
}
Handle Firebase iOS Auth Errors
Firebase already does this for you. Erase the sign in method and just run the create user method using an email that already exists and FIRAuthErrorCodeEmailAlreadyInUse will be returned. Check this out for more info
I am using email + password authentication with Firebase for my app. Login works, and I use observeAuthEventWithBlock to check if a user is logged in - in order not to bring up the Login page. If I press the home button and open the app again, there is no problem. The problem I am having is if I force-quit the app. When I re-open, I have to log-in again.
Some notes about the setup before I show my login code.
There is a LoginViewController - not embedded - built w/ Storyboard
This is connected to a Navigation Controller
Which is what the first screen is embedded in, and the rest of the app uses this Nav Controller.
Login code:
#IBAction func loginButtonPressed() {
let userEmail = emailTextField.text
self.ref.authUser(self.emailTextField.text, password: self.passwordTextField.text, withCompletionBlock: { (error, auth) -> Void in
guard error == nil else {
if let errorCode = FAuthenticationError(rawValue: error.code) {
switch (errorCode) {
case .EmailTaken:
self.displayMessage("Email Error", theMessage: "This email is taken")
case .InvalidEmail:
self.displayMessage("Email Error", theMessage: "This email is invalid")
case .UserDoesNotExist:
self.displayMessage("User Error", theMessage: "A user account for email: \(userEmail!) does not exist")
case .InvalidPassword:
self.displayMessage("Password Error", theMessage: "The password is incorrect")
case .NetworkError:
self.displayMessage("Network Error", theMessage: "Seems like there's a problem with your internet connection")
default:
return
}
}
return //set Unknown Error Alert here
}
print("LOGGED IN: segue from loginButtonPressed")
self.userLoggedIn = true
print("user is logged in? \(self.userLoggedIn)")
self.performSegueWithIdentifier("loginLocaleSegue", sender: self)
})
}
Check if user is logged in - if so segue to navcon, pop it and display embedded View Controller:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if self.userLoggedIn.boolValue == true {
ref.observeAuthEventWithBlock { (authData) -> Void in
if authData != nil {
let navCon: UINavigationController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("MainNavigationController") as! UINavigationController
self.presentViewController(navCon, animated: false, completion: nil)
navCon.popViewControllerAnimated(false)
print("user is authenticated: \(authData.providerData["email"] as! String)")
print("segues from viewDidAppear")
} else {
return
}
}
}
}
I've seen questions related to Firebase auth which state that Authdata is stored in Keychain by default, which causes problems with Authdata persisting even after deletion of app, but I'm experiencing the total opposite issue. Any ideas?
From what I can tell, you're not writing "self.userLoggedIn = true" to any database, so it makes sense that it continues being "True" while you have the app on idle, but once you close the application, it then becomes nil (no value), this is because it's just chilling in the background while the app is open, but not completely closed. Try writing this to your Firebase database, as outlined in this tutorial, and see if that helps.
https://www.raywenderlich.com/109706/firebase-tutorial-getting-started