How to have hashed passwords in Firebase using Swift? - swift

I was following an Uber clone tutorial. I can get log in, registration, and logout working, but the passwords don't seem to be hashed; I can see them plainly in my Firebase database.
Here is my code. First login/sign up/logout function saved in a 'plugins' folder separate from controllers.
import Foundation
import FirebaseAuth
typealias LoginHandler = (_ msg: String?) -> Void;
struct LoginErrorCode {
static let INVALID_EMAIL = "Invalid email, please provide a real email address";
static let WRONG_PASSWORD = "Wrong Password, Please Try Again";
static let PROBLEM_CONNECTING = "Problem Connecting to Database. Please Try Later";
static let USER_NOT_FOUND = "User Not Found, Please Register";
static let EMAIL_ALREADY_IN_USE = "Email Already In Use, Please Use Different Email";
static let WEAK_PASSWORD = "Password Should Be At Least 6 Characters";
}
class AuthProvider {
private static let _instance = AuthProvider();
static var Instance: AuthProvider {
return _instance;
}
func login(withEmail: String, password: String, loginHandler: LoginHandler?) {
FIRAuth.auth()?.signIn(withEmail: withEmail, password: password, completion: { (user, error) in
if error != nil {
self.handleErrors(err: error as! NSError, loginHandler: loginHandler);
} else {
loginHandler?(nil);
}
})
} //login func
func signUp(withEmail: String, password: String, loginHandler: LoginHandler?) {
FIRAuth.auth()?.createUser(withEmail: withEmail, password: password, completion: { (user, error) in
if error != nil {
self.handleErrors(err: error as! NSError, loginHandler: loginHandler);
} else {
if user?.uid != nil {
// store the user to database
DBProvider.Instance.saveUser(withID: user!.uid, email: withEmail, password: password)
//log in the user
self.login(withEmail: withEmail, password: password, loginHandler: loginHandler)
}
}
})
} //sign up func
func logOut() -> Bool {
if FIRAuth.auth()?.currentUser != nil {
do {
try FIRAuth.auth()?.signOut();
return true;
} catch {
return false;
}
}
return true
}
private func handleErrors(err: NSError, loginHandler: LoginHandler?) {
if let errCode = FIRAuthErrorCode(rawValue: err.code) {
switch errCode {
case .errorCodeWrongPassword:
loginHandler?(LoginErrorCode.WRONG_PASSWORD);
break;
case .errorCodeInvalidEmail:
loginHandler?(LoginErrorCode.INVALID_EMAIL);
break;
case .errorCodeUserNotFound:
loginHandler?(LoginErrorCode.USER_NOT_FOUND);
break;
case .errorCodeEmailAlreadyInUse:
loginHandler?(LoginErrorCode.EMAIL_ALREADY_IN_USE);
break;
case .errorCodeWeakPassword:
loginHandler?(LoginErrorCode.WEAK_PASSWORD);
break;
default:
loginHandler?(LoginErrorCode.PROBLEM_CONNECTING);
break;
}
}
}
} //class
And the controller:
import UIKit
import FirebaseAuth
class SignInVC: UIViewController {
private let DRIVER_SEGUE = "DriverVC";
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func login(_ sender: Any) {
if emailTextField.text != "" && passwordTextField.text != "" {
AuthProvider.Instance.login(withEmail: emailTextField.text!, password: passwordTextField.text!, loginHandler: { (message) in
if message != nil {
self.alertTheUser(title: "Problem With Authentication", message: message!);
} else {
self.performSegue(withIdentifier: self.DRIVER_SEGUE, sender: nil)
}
});
} else {
alertTheUser(title: "Email And Password Are Required", message: "Please enter email and password");
}
}
#IBAction func signUp(_ sender: Any) {
if emailTextField.text != "" && passwordTextField.text != "" {
AuthProvider.Instance.signUp(withEmail: emailTextField.text!, password: passwordTextField.text!, loginHandler: { (message) in
if message != nil {
self.alertTheUser(title: "Problem With Creating New Account", message: message!)
} else {
self.performSegue(withIdentifier: self.DRIVER_SEGUE, sender: nil)
}
})
} else {
alertTheUser(title: "Email And Password Are Required", message: "Please enter email and password");
}
}
private func alertTheUser(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert);
let ok = UIAlertAction(title: "OK", style: .default, handler: nil);
alert.addAction(ok);
present(alert, animated: true, completion: nil)
}
} //class

Try using updatePassword(_ password: String, completion: FirebaseAuth.FIRUserProfileChangeCallback? = nil) on FIRUser.

Related

an alert function that i created is calling several times for no reason

I am working on a project using firebase database and I save the users with their displayName instead of uid. I check if the displayName of the user who is trying to signup is on the list of displayNames on firebase and if not I allow user to signup with that displayName.
here is my signUp function;
func signUp(email: String, password: String) {
//gets the user data in the firebase
Database.database().reference().child("users").observe(.value) { [self] (snapshot) in
if snapshot.hasChild(self.userNameTxtField.text!){ //checking the displayName
self.present(alertFunction(message: "Seçmiş olduğunuz kullanıcı adı daha önceden alınmış."), animated: true)
} else {
Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in
if let error = error as NSError? {...} else {
self.signIn(email: email, password: password)
}
}
}
}
}
and here is my signIn function;
func signIn(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { (authResult, error) in
if let error = error as NSError? {...} else {
self.activityIndicator.stopAnimating()
self.view.isUserInteractionEnabled = true
//create database reference
self.ref = Database.database().reference()
//create new child and write a value on the existance child
if self.userNameTxtField.text == ""{
print("User Name can not be nill!")
self.present(self.alertFunction(message: "Kullanıcı adı boş bırakılamaz"), animated: true)
} else {
UserDefaults.standard.setValue(true, forKey: "userSignedIn")
if let currentUser = Auth.auth().currentUser?.createProfileChangeRequest() {
currentUser.displayName = self.userNameTxtField.text!
currentUser.commitChanges(completion: { error in
if let error = error {
print(error)
} else {
print("DisplayName changed")
self.ref.child("users").child(currentUser.displayName!).setValue(["nickname": self.userNameTxtField.text ?? ""])
self.ref.child("users/\(currentUser.displayName!)/step_count").setValue(Int(0))
self.ref.child("users/\(currentUser.displayName!)/total_point").setValue(Int(0))
self.ref.child("users/\(currentUser.displayName!)/onesignal_player_id").setValue("")
self.performSegue(withIdentifier: "showMainFromRegister", sender: self)
}
})
}
}
}
}
}
and finally here is my actionFunction;
func alertFunction(message: String) -> UIAlertController {
let alert = UIAlertController(title: "Uyarı!", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Tamam", style: .cancel, handler: nil))
self.activityIndicator.stopAnimating()
self.view.isUserInteractionEnabled = true
return alert
}
I call the signUp function after a button clicked and signUp func is calling the signIn function and if everything goes fine signIn function calls the performSegue function but after the performSegue
snapshot.hasChild(self.userNameTxtField.text!)
is triggered several time and the alert;
self.present(alertFunction(message: "Seçmiş olduğunuz kullanıcı adı daha önceden alınmış."), animated: true)
is displaying for no reason.
How can I solve the problem?
Replace
// listens for any change
.observe(.value) { [self] (snapshot) in
with
// listens for a change only once
.observeSingleEvent(of: .value, with: { [weak self] snapshot in

Does not add a user to Firebase

I am trying to add users to my Firebase cloud
I connected my project to the console.firebase
While I fill in the email and password it is not adding to my firebase.
I have the following code:
#IBAction func registerButton(_ sender: Any) {
signUp()
}
this is a button for register
and this is the func signup:
func signUp (){
let name = nameValue.text
let password = passwordValue.text
let email = emailValue.text
if (!password!.isEmpty && !email!.isEmpty) {
Auth.auth().createUser(withEmail: email ?? "", password: password ?? "") { (result, error) in
if error == nil {
if let result = result {
}
}
}
}
else {
showAlert()
}
}
Can anybody help to figure out this problem?
here is the solution to my problem:
if (!name!.isEmpty && !password!.isEmpty && !email!.isEmpty) {
Auth.auth().createUser(withEmail: email ?? "", password: password ?? "") { (authResult, error) in
if let e = error {
print(e.localizedDescription)
} else {
// self.performSegue(withIdentifier: "main", sender: self)
}
}
}

How to Log-in with Firebase in Swift UI?

I can create user through my code and get in to the next view but I can not log in with that mail address and password I just created. On the other hand, when I create a user in Firebase authentication page without programmatically, I can log in with that mail address and password. I don't know why this is happening.
My login button's codes are as following...
Button(action: {
self.verify()
}) {
Text("Log In")
}
func verify(){
if self.mail != "" && self.pass != ""{
Auth.auth().signIn(withEmail: self.mail, password: self.pass) { (res, err) in
if err != nil{
self.error = err!.localizedDescription
self.alert.toggle()
return
}
print("success")
UserDefaults.standard.set(true, forKey: "status")
NotificationCenter.default.post(name: NSNotification.Name("status"), object: nil)
}
}
else{
self.error = "Please fill all the contents properly"
self.alert.toggle()
}
}
My signUp button's codes are as following...
Button(action: {
self.register()
}) {
Text("Sign Up")
}
func register(){
if self.mail != ""{
if self.pass == self.repass{
Auth.auth().createUser(withEmail: self.mail, password: self.pass) { (res, err) in
if err != nil{
self.error = err!.localizedDescription
self.alert.toggle()
return
}
print("success")
UserDefaults.standard.set(true, forKey: "status")
NotificationCenter.default.post(name: NSNotification.Name("status"), object: nil)
}
}
else{
self.error = "Password mismatch"
self.alert.toggle()
}
}
else{
self.error = "Please fill all the contents properly"
self.alert.toggle()
}
}
To Sign In in Firebase I recommend some updates in your code:
Use completion to your Sign In and Sign Up functions, this way you know for sure that Firebase is answer you.
Handle listener AuthStateDidChangeListenerHandle. This listener gets called whenever the user's sign-in state changes.
API Authentification:
class AuthService {
static func signInUser(email: String, password: String, onSucces: #escaping() -> Void, onError: #escaping (_ errorMessage : String) -> Void ) {
Auth.auth().signIn(withEmail: email, password: password) { (authData, error) in
if (error != nil) {
print(error!.localizedDescription)
onError(error!.localizedDescription)
return
}
//Sign In Code
onSuccess()
}
static func signUpUser(email: String, password: String, username: String, onSucces: #escaping() -> Void, onError: #escaping (_ errorMessage : String) -> Void ) {
Auth.auth().createUser(withEmail: email, password: password) { (authData, error) in
if (error != nil) {
print(error!.localizedDescription)
onError(error!.localizedDescription)
return
}
//Sign Up Code
onSuccess()
}
}
}
in your View or ViewModel:
func verify() {
if self.mail != "" && self.pass != ""{
AuthService.signUpUser(email: email, password: password, username: username, onSucces: {
print("Sign In!")
}) { (error) in {
print("Error \(error)")
})
}
}
Class Session, to handle Auth Listener
class SessionAuth : ObservableObject {
#Published var isLoggedIn = true
var handle : AuthStateDidChangeListenerHandle?
func listenAuthentificationState() {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if let user = user {
//You are log in
// Your login process code
self.isLoggedIn = true
}
else {
//You are not
self.isLoggedIn = false
}
}
}
Your main View:
struct ContentView: View {
#ObservedObject var session : SessionAuth //or EnvironmentObject
func listen() {
session.listenAuthentificationState()
}
var body: some View {
Group {
if session.isLoggedIn {
MainLoggedView()
}
else {
SignInView()
}
}.onAppear(perform: listen)
}
}
In if else()
you need to "return ();"
and,
you should create login activity in programa manner.
FOR bETTER ResulT.

Xcode Firebase | Cannot convert value of type'AuthDataResult' to expected argument type 'User'

I tried literally tried every possible option to write it, but I can't seem to figure out the solution.
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (user, error) in
if error != nil {
print(error!)
}else {
self.createProfile(user!) //Here's the problem described in the title //
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}
func createProfile(_ user: User) {
let newUser = ["email": user.email, "photo": "https://firebasestorage.googleapis.com/v0/b/ecoapp2.appspot.com/o/photos-1.jpg?alt=media&token=ee104f2d-ed9a-4913-8664-04fd53ead857"]
self.databaseRef.child("profile").child(user.uid).updateChildValues(newUser) { (error, ref) in
if error != nil {
print(error!)
return
}
print("Profile successfully created")
}
}
You need
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
// ...
guard let user = authResult.user else { reurn }
self.createProfile(user)
}
func createProfile(_ user: FIRUser ) { --- }
Starting from Firebase API 5.0 it's createUser() method returns FIRAuthDataResultCallback instead of User object directly.
In your case you can fix it my making following changes:
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (user, error) in
if error != nil {
print(error!)
}else {
self.createProfile(user!.user) //Here's how you can fix it
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}
For more code readability I would replace your code like below:
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (authResult, error) in
if error != nil {
print(error!)
}else {
self.createProfile(authResult!.user)
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}

Save User's name in Firebase - Swift

I have three text field in my registration form. The e-mail id and password of the user are used by the Firebase SignUp method to create a new user. But I also want to save the user's name according to what they input.
My current code is;
#IBAction func registerPressed(_ sender: Any) {
SVProgressHUD.show(withStatus: "Setting you up")
dismissUIElements(value: false)
let currentUserName = userName.text
if currentUserName?.isEmpty == false {
FIRAuth.auth()?.createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: { (user, error) in
if error != nil {
print(error!)
SVProgressHUD.dismiss()
self.dismissUIElements(value: true)
} else {
print("Registration Successful!")
SVProgressHUD.dismiss()
self.dismissUIElements(value: true)
self.performSegue(withIdentifier: "goToSelectionFromRegister", sender: self)
}
})
}
else {
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "Please enter your name!")
SVProgressHUD.dismiss(withDelay: 1)
self.dismissUIElements(value: true)
}
}
You need a function that will register the user and then create the child for that user in Firebase.
let databaseRef=//your path to users.
func registerUser(userUsername userName:String, userEmail email:String, userPassword password: String, userCreationComplete: #escaping (_ status: Bool, _ error: Error?) -> ()) {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
guard let user = user else {
userCreationComplete(false, error)
return
}
let userData = ["userName": userName.text] as [String : Any]
ref.child(user.uid).updateChildValues(userData)
userCreationComplete(true, nil)
}
}
Then you call the function from within registerPressed() and you pass it the textfield values but make sure that none of them is empty.
You will create a new data table that stores that info. It won't be done in the create user function.
// create a reference to the DB
ref = Database.database().reference(fromURL: "https://your-project-name.firebaseio.com/")
//variables to store data
var myID : String?
var myName : String?
var myNumber : String?
var myEmail : String?
// creating the save user function
func saveUser(_ completion: #escaping(_ error: Error?) -> Void) {
if PageDataSource.sharedInstance.crudIsAvailable == true {
let usersRef = ref.child("users")
let myUserRef = usersRef.child(id)
myUserRef.updateChildValues(["User ID": id,
"Name": myName,
"Email": myEmail,
"Phone": .myNumber], withCompletionBlock: { (error, ref) in
if error != nil {
completion(error!)
} else {
completion(nil)
}
})
} else {
completion(NSError(domain: "Unavailable", code: 0, userInfo: nil))
}
}
// call the method like this to perform the save
func storeUser(completion: #escaping(_ completed: Bool, _ error: NSError?)-> Void) {
if let user = Auth.auth().currentUser {
myID = user.uid
myName = user.displayName
myEmail = user.email
// etc.,
completion(true,nil)
} else {
completion(false,NSError(domain: "No Current User", code: 1, userInfo: nil))
}
}