According to Firebase site, I am using this code to create a new user:
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {});
How can I add display name and photo url to Auth when creating the new user?
This link shows the supported user data returned from an identity provider in Auth.
You can update your profile with FIRUserProfileChangeRequest class .. check this Doc.
let user = FIRAuth.auth()?.currentUser
if let user = user {
let changeRequest = user.profileChangeRequest()
changeRequest.displayName = "Jane Q. User"
changeRequest.photoURL =
NSURL(string: "https://example.com/jane-q-user/profile.jpg")
changeRequest.commitChangesWithCompletion { error in
if let error = error {
// An error happened.
} else {
// Profile updated.
}
}
}
I think this should solve it for you, let me know if you need anything else. or have any further questions on this matter.
func handleSignUp() {
guard let userName = userNameTF.text else { return }
guard let email = emailTF.text else { return }
guard let password = passwordTF.text else { return }
guard let image = profileImage.image else { return }
continueButton.setBackgroundImage(#imageLiteral(resourceName: "inactiveButtonBG"), for: .normal)
activityIndicator.startAnimating()
Auth.auth().createUser(withEmail: email, password: password) { user, error in
if error == nil && user != nil {
print("User created!")
self.uploadProfileImage(image: image) { url in
if url != nil {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = userName
changeRequest?.photoURL = url
changeRequest?.commitChanges { error in
if error == nil {
self.saveProfile(username: userName, profileImageURL: url!) { success in
if success {
print("Success upload of profile image")
self.dismiss(animated: true, completion: nil)
}
}
self.dismiss(animated: true, completion: nil)
} else {
guard let message = error?.localizedDescription else { return }
self.userAlert(message: message)
}
}
} else {
self.userAlert(message: "Unable to load profile image to Firebase Storage.")
}
}
self.dismiss(animated: true, completion: nil)
} else {
guard let message = error?.localizedDescription else { return }
self.userAlert(message: message)
}
}
}
To change/add the display name:
user!.createProfileChangeRequest().displayName = "Your name"
To change/add photoURL
user!.createProfileChangeRequest().photoURL = URL(string: "image url")
Simply you can solve your problem as follow.
1) Create a user using following statement.
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {});
2) success of above statement Please authenticate this user as follow.
self.rootRef.authUser(email, password)
// USER_ID = Here you get user_ID
3) Success of above function set user name and profile picture to user as follow.
usersRef.updateChildValues(dict, withCompletionBlock:
-Here userRef contain your userDetails/USER_ID
Might be work for you.
i have code but work for older firebase version so not work for you otherwise i had share with you.
I think you mean adding display name and photo url to Firebase Database after Auth. This is pretty much what I do all on same registration.
if let email = emailField.text where email != "", let pwd = passwordField.text where pwd != ""{
FIRAuth.auth()?.createUserWithEmail(email, password: pwd, completion: { (user, error) in
if error != nil {
print("DEVELOPER: Unable to authenticate with Firebase using email")
}else {
print("DEVELOPER: Successfully authenticated with Firebase using email")
if let user = user {
let userData = ["provider": user.providerID, "userName": "\(user.displayName)", "profileImg": "\(user.photoURL)"]
self.completeMySignIn(user.uid, userData: userData)
}
}
})
} else {
// Email and Password where not filled in
}
}
Now adding your profile image and users username in DB here
func completeMySignIn(id: String, userData: Dictionary<String, String>){
{YourFirebaseUserURL}.updateChildValues(userData)
}
You can use the Firebase Admin SDK in Firebase Function exactly for your purpose, i.e. to fill up other user properties as the user is created:
const admin = require("firebase-admin");
// Put this code block in your Firebase Function:
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
displayName: `${fname} ${lname}`,
disabled: false
})
But creating user with Firebase Admin SDK may give you problem in sending email verification because the promise does not return the User object that has the sendEmailVerification() method. You may eventually need to use the Firebase client API (as shown in your own code) to create the user and update the user profile before sending the email verification:
var user = firebase.auth().currentUser;
user.updateProfile({
displayName: "Jane Q. User",
photoURL: "https://example.com/jane-q-user/profile.jpg"
}).then(function() {
// Update successful.
}).catch(function(error) {
// An error happened.
});
It make sense to update the displayName before sending email verification so that the Firebase email template will greet the new user with proper name rather than just Hello (sounds like a spam) when the displayName is not set.
Related
With the help of detailed tutorials, I was able to create a registration form and an email login, including a Google login.
I ran into a number of issues where I needed a few things, firstly I can't find any relevant information on the web regarding creating unique usernames so that I can log in via them other than email.
The second problem: I need to create the simplest user page, where all the necessary information about the user would be located, such as: avatar, email and username, as well as the function to change the avatar and password.
At the moment my database looks like this:
enter image description here
LoginViewController:
#IBAction func loginTapped(_ sender: Any) {
// Create cleaned version of the text fields
let email = usernameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// Sign in in the user
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
if error != nil {
// Couldn't sign in
self.errorLabel.text = error!.localizedDescription
self.errorLabel.alpha = 1
}
else {
let homeViewController =
self.storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as?
UITabBarController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
UserDefaults.standard.set("email", forKey: "email")
}
}
}
SignUpViewController:
#IBAction func signUpTapped(_ sender: Any) {
guard let password = passwordTextField.text, !password.isEmpty,
let confirm = confirmPasswordTextField.text, !confirm.isEmpty else {
showError(message: "Password field is empty.")
return
}
guard password == confirm else {
showError(message: "Passwords do not match.")
return
}
// Validate the fields
let error = validateFields()
if error != nil {
// There's somthing wrong with the field, show the error message
showError(message: error!)
}
else {
// Create cleaned versions of the data
let username = usernameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
//let confirmpassword = confirmPasswordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// Create the user
Auth.auth().createUser(withEmail: email, password: password) { (result, err) in
// Check for errors
if err != nil {
// There was an error creating the user
self.showError(message: "Error creating user.")
}
else {
// User was created successfully, now store username and other data needed
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["username":username, "uid": result!.user.uid ]) {
(error) in
if error != nil {
// Show error message
self.showError(message: "Error saving user data.")
}
}
// Transition to the home screen
self.transitionToHome()
}
}
}
}
func showError(message:String) {
errorLabel.text = message
errorLabel.alpha = 1
}
func transitionToHome() {
let homeViewController =
storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as?
UITabBarController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
If I missed any important information, I will be glad if you ask and I will provide everything to you!
Thank you very much in advance for your time!
When creating a new user, I need to log them out and then send a verification email to ensure that they own the email address. Currently my code creates the user and executes the "sendEmailVerification" call but keeps the user logged in. How can I log my user out and check that they have verified their email?
func signUp(with email: String, password: String, firstName: String, lastName: String) {
self.presentActivityView()
Auth.auth().createUser(withEmail: email, password: password) {[unowned self] (user, error) in
DispatchQueue.main.async { [unowned self] in
self.dismissActivityView()
if let err = error {
self.addAlertController(title: "Error!", message: err.localizedDescription)
} else {
let changeReq = Auth.auth().currentUser?.createProfileChangeRequest()
changeReq?.displayName = firstName + " " + lastName
if let url = self.profilePicURLString {
changeReq?.photoURL = URL(string: url)
}
changeReq?.commitChanges(completion: { (error) in
if error == nil {
//Profile updated successfully
}else {
//Profile not updated successfully
}
})
Auth.auth().currentUser?.sendEmailVerification(completion: { (error) in
if error == nil {
//Verification initiated successfully
}else {
print("Error: \(error)")
}
})
let vc = MainStoryboard.instantiateViewController(withIdentifier: "SNStoryFeedController") as! SNStoryFeedController
let nc = UINavigationController(rootViewController: vc)
UIApplication.shared.keyWindow?.rootViewController = nc
}
}
}
}
The only thing you should do is sign out from your own application:
// for FIRAuth
try? Auth.auth()?.signOut()
// for GoogleSignIn
GIDSignIn.sharedInstance().signOut()
The safari part is handled by the system and you don't need to worry about.
I'm new in programming and still learning in swift language.
I hope you could help me with this issue.
when I try to signup the Userinfo shows in database but when I try to login the user info disappears why is that so? can't figure it out.
Here is how i signup
#objc func handleSignUp() {
guard let username = usernameField.text else { return }
guard let email = emailField.text else { return }
guard let pass = passwordField.text else { return }
guard let image = profileImageView.image else { return }
setContinueButton(enabled: false)
continueButton.setTitle("", for: .normal)
activityView.startAnimating()
Auth.auth().createUser(withEmail: email, password: pass) { user, error in
if error == nil && user != nil {
print("User created!")
// 1. Upload the profile image to Firebase Storage
self.uploadProfileImage(image) { url in
if url != nil {
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = username
changeRequest?.photoURL = url
changeRequest?.commitChanges { error in
if error == nil {
print("User display name changed!")
self.saveProfile(username: username, profileImageURL: url!) { success in
if success {
self.dismiss(animated: true, completion: nil)
} else {
self.resetForm()
}
}
} else {
print("Error: \(error!.localizedDescription)")
self.resetForm()
}
}
} else {
self.resetForm()
}
}
} else {
self.resetForm()
}
}
}
And here is how I log in
#objc func handleSignIn() {
guard let email = emailField.text else { return }
guard let pass = passwordField.text else { return }
setContinueButton(enabled: false)
continueButton.setTitle("", for: .normal)
activityView.startAnimating()
Auth.auth().signIn(withEmail: email, password: pass) { user, error in
if error == nil && user != nil {
self.dismiss(animated: false, completion: nil)
_ = Auth.auth().currentUser
} else {
print("Error logging in: \(error!.localizedDescription)")
self.resetForm()
}
}
I don't know what seems to be the problem
I'm not familiar with firebase but according to their documentation this is "da way" :
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
print("ERROR [ signIn ] => \(error)")
// self.resetForm()
} else {
if let user = user {
let uid = user.uid
let email = user.email
print("Authorised User => \(uid) ... \(email)")
}
}
}
If after trying the above code and you see this output ERROR [ signIn ] => whatever error...", then it's your signIn that failed. If you see this output Authorised User => SomeUID ... SomeEMAIL, then you signed in successfully and your user's data is still in the database.
I hope this helps you find "da way"
If all else fails:
You can change browsers and check your database again ? Try a couple of browsers. This worked for some people
Good luck!
I am new to firebase and I'm trying to learn how to create users. My problem is that when i use the createUserWithEmail completion block via a button, for some reason the unique identifier, the uid, is not generated. This prevents me from storing the associated username and password under the uid in the JSON tree. My code is as follows (I have defined databaseRef in a separate swift file as a global constant using "let databaseRef = FIRDatabase.database().reference()")
#IBAction func createAccount(sender: AnyObject) {
var username = usernameField.text
var email = emailField.text
var password = passwordField.text
if username != "" && email != "" && password != "" {
FIRAuth.auth()?.createUserWithEmail(email!, password: password!, completion: { (user, error) in
databaseRef.child("users/(user.uid)/username").setValue(username)
databaseRef.child("users/(user.uid)/password").setValue(password)
databaseRef.child("users/(user.uid)/uid").setValue(user?.uid)
})
} else {
print("please complete all fields")
}
}
I know the uid is not generated for two reasons. Firstly, when i run the above code and enter in values for each of my texts fields, the app crashes. Secondly, if i delete the code that deals with setting the values and replace it with print(user.uid), a value of nil is returned. What am i missing? I can understand that the uid is a very important part of creating a user.
***Here is the solution I came up with
#IBAction func createAccount(sender: AnyObject) {
var username = usernameField.text
var email = emailField.text
var password = passwordField.text
if username != "" && email != "" && password != "" {
FIRAuth.auth()?.createUserWithEmail(email!, password: password!, completion: { (user, error) in
if let user = FIRAuth.auth()?.currentUser {
databaseRef.child("users/\(user.uid)/username").setValue(username)
databaseRef.child("users/\(user.uid)/password").setValue(password)
databaseRef.child("users/\(user.uid)/email").setValue(email)
print(user.uid)
} else {
print("no user")
}
})
} else {
print("please complete all fields")
}
Swift 4, 2018 solution for anyone who's interested:
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
// guard against errors and optionals
guard error == nil else { return }
guard let user = user else { return }
let userObject = [
"uid": user.uid,
"username": username,
"password": password, // I don't recommend storing passwords like this by the way
"email": email
] as [String:Any]
databaseRef.child("users").child(user.uid).setValue(userObject)
}
Swift 5.1, 2022 solution for anyone who's interested:
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
// guard against errors and optionals
guard error == nil else { return }
guard let user = user else { return }
let userObj = ["uid": user.user.uid, "username": username, "email": email] as [String:Any]
databaseRef.child("users/\(user.user.uid))".setValue(userObj)
I am building an app that uses Firebase's email and password login feature. I am having the user register with a username, email, and password. I am struggling with how to stop the user from being created if the username is not unique. I have been reading other questions (specifically Firebase-android-make-username-unique and how-prevent-username-from-duplicate-signup-infirebase) but I have still not gotten it to fully work.
I followed the instructions in the first link above and set up my data structure as:
app : {
users: {
"some-user-uid": {
email: "test#test.com"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
and my security rules as:
"users": {
"$uid": {
".write": "auth !== null && auth.uid === $uid",
".read": "auth !== null && auth.provider === 'password'",
"username": {
".validate": "
!root.child('usernames').child(newData.val()).exists() ||
root.child('usernames').child(newData.val()).val() == $uid"
}
}
}
With this setup, if I try to create a new user with a username that already exists, it stops the user from being added to my data structure. When the below code is called, it prints "User Data could not be saved" if the username is a duplicate.
func createNewAccount(uid: String, user: Dictionary<String, String>) {
USER_REF.childByAppendingPath(uid).setValue(user, withCompletionBlock: {
(error:NSError?, ref:Firebase!) in
if (error != nil) {
print("User Data could not be saved.")
} else {
print("User Data saved successfully!")
}
})
}
func addUsernameToUsernamePath (userData: Dictionary<String, String>) {
USERNAME_REF.updateChildValues(userData)
}
Here is where I am stuck. My create account method below doesn't call the above two methods until createUser and authUser are called (Which I need to get the uid). My problem is the user still gets created as a registered user and my security rules just keep the users information from being added to my data structure. I need to figure out how to stop the user from being created if there is a duplicate username.
#IBAction func createAccount() {
let username = usernameField.text
let email = emailField.text
let password = passwordField.text
if username != "" && email != "" && password != "" {
// Set Email and Password for the New User.
DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in
if error != nil {
print("Error: \(error)")
if let errorCode = FAuthenticationError(rawValue: error.code) {
switch (errorCode) {
case .EmailTaken:
self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
default:
self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
}
}
} else {
DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
err, authData in
let user = ["provider": authData.provider!, "email": email!, "username": username!]
let userData = [username!: authData.uid!]
DataService.dataService.createNewAccount(authData.uid, user: user)
DataService.dataService.addUsernameToUsernamePath(userData)
})
EDIT
Here is my updated createAccount method that solved my issue.
#IBAction func createAccount() {
let username = usernameField.text
let email = emailField.text
let password = passwordField.text
if username != "" && email != "" && password != "" {
DataService.dataService.USERNAME_REF.observeEventType(.Value, withBlock: { snapshot in
var usernamesMatched = false
if snapshot.value is NSNull {
usernamesMatched = false
} else {
let usernameDictionary = snapshot.value
let usernameArray = Array(usernameDictionary.allKeys as! [String])
for storedUserName in usernameArray {
if storedUserName == self.usernameField.text! {
usernamesMatched = true
self.signupErrorAlert("Username Already Taken", message: "Please try a different username")
}
}
}
if !usernamesMatched {
// Set Email and Password for the New User.
DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in
if error != nil {
print("Error: \(error)")
if let errorCode = FAuthenticationError(rawValue: error.code) {
switch (errorCode) {
case .EmailTaken:
self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
default:
self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
}
}
} else {
// Create and Login the New User with authUser
DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
err, authData in
let user = ["provider": authData.provider!, "email": email!, "username": username!]
let userData = [username!: authData.uid!]
// Seal the deal in DataService.swift.
DataService.dataService.createNewAccount(authData.uid, user: user)
DataService.dataService.addUsernameToUsernamePath(userData)
})
You could allow sign up without a valid username, and have a separate "set username" screen that you show in the event of a partial registration.
Define your security rules to check for a non-null username before allowing writes to other parts of your database.
I was able to get it working by updating createAccount() to the code below.
#IBAction func createAccount() {
let username = usernameField.text
let email = emailField.text
let password = passwordField.text
if username != "" && email != "" && password != "" {
// Checks for internet connection before saving the meetup. Returns if there is no internet connection.
let reachability = try! Reachability.reachabilityForInternetConnection()
if reachability.currentReachabilityStatus == .NotReachable {
let internetAlert = UIAlertController(title: "No Internet Connection", message: "Please make sure your device is connected to the internet.", preferredStyle: .Alert)
let internetAlertAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
internetAlert.addAction(internetAlertAction)
presentViewController(internetAlert, animated: true, completion: nil)
return
}
DataService.dataService.USERNAME_REF.observeEventType(.Value, withBlock: { snapshot in
var usernamesMatched = false
if snapshot.value is NSNull {
usernamesMatched = false
} else {
let usernameDictionary = snapshot.value
let usernameArray = Array(usernameDictionary.allKeys as! [String])
for storedUserName in usernameArray {
if storedUserName == self.usernameField.text! {
usernamesMatched = true
self.signupErrorAlert("Username Already Taken", message: "Please try a different username")
}
}
}
if !usernamesMatched {
// Set Email and Password for the New User.
DataService.dataService.BASE_REF.createUser(email, password: password, withValueCompletionBlock: { error, result in
if error != nil {
print("Error: \(error)")
if let errorCode = FAuthenticationError(rawValue: error.code) {
switch (errorCode) {
case .EmailTaken:
self.signupErrorAlert("Email In Use", message: "An account has already been created for this email address.")
default:
self.signupErrorAlert("Oops!", message: "Having some trouble creating your account. Please try again or check your internet connection.")
}
}
} else {
// Create and Login the New User with authUser
DataService.dataService.BASE_REF.authUser(email, password: password, withCompletionBlock: {
err, authData in
let user = ["provider": authData.provider!, "email": email!, "username": username!]
let userData = [username!: authData.uid!]
// Seal the deal in DataService.swift.
DataService.dataService.createNewAccount(authData.uid, user: user)
DataService.dataService.addUsernameToUsernamePath(userData)
})