I am making an app that logs you in to a certain group, Currently I have it where you log in as such:
let loginUser = PFUser()
loginUser.username = username.text!
loginUser.password = password.text!
PFUser.logInWithUsername(inBackground: loginUser.username!, password: loginUser.password!, block: { (user, error) in
if user != nil { //Continue with code
but what I'd like to do would be to add in my group login ID field so that I do not have to make an additional call to match their groupID TextField with their currently set up groupID. I don't know if you can and I couldn't find it in documentation. Something Like:?
let loginUser = PFUser()
loginUser.username = username.text!
loginUser.password = password.text!
loginUser["groupID"] = groupID.text!
PFUser.logInWithUsername(inBackground: loginUser.username!, password: loginUser.password!, login["groupID"]: login.groupID block: { (user, error) in
if user != nil { //Now Checks login AND for group id...
Now obviously I know it's not that easy but does anybody have a mildly easy work around for this? Right now afterwords i'm comparing the
user["groupID"] == groupID.text! {
// Then Login to group is a success!
// Segue to next View Controller
} else {
// Let the user know the Log In was "unsuccessful" even though they logged in but they got their groupID wrong
// Log User Out
// Clear groupID Text Field & Display alert so they can reattempt log in
}
Any help would be appreciated!
Thanks!
I suggest you to use "cloud code", you might want to create your own login method using some other language like javascript.
Related
I am creating an app that allow user sign up/login through Firebase API. The flow is that the user signs up a new account, is taken to an email verification page (the user is sent a verification email at this point), then they may login after verifying their account. The problem is, on the first time they tap "Login", the alert is shown that they still need to be verified (even after verifying) but when they tap again it will successfully log them in. I want the user to be able to login successfully first time straight after verifying. Thank you in advance for the help.
private func login() {
let userEmail = textFrom(loginEmail)
let userPassword = textFrom(loginPassword)
let authUser = Auth.auth().currentUser
self.loginButton.loadingIndicator(show: true)
guard let isVerified = authUser?.isEmailVerified else { return }
Auth.auth().signIn(withEmail: userEmail, password: userPassword, completion: {(user, error) in
if let firebaseError = error {
self.loginButton.loadingIndicator(show: false)
self.showError(firebaseError)
}
if authUser != nil && !isVerified {
self.loginButton.loadingIndicator(show: false)
self.presentAlert(withTitle: "Verify Email", message: "Please verify your email first before logging in")
self.clearFields()
} else {
self.loginButton.loadingIndicator(show: false)
self.transitionToHome()
}
})
}
Also, I know this isn't Github but I am new to using Firebase, if you think my logic can be improved (this function is called in the IBAction of the login button) then please let me know. Thank you :)
Are you positive that the alert you quoted is the one being returned? No other similarly worded alerts coming from somewhere else?
If so, then the only way it can be shown is if isVerified is false and authUser is not nil (which is redundant, because if it was nil, the guard let ... optional chaining would have immediately returned from the function).
So it looks like authUser.isEmailVerified is returning false. You can verify this by adding a breakpoint at the line: if authUser != nil && !isVerified {
Without knowing more it's impossible to say what's going on.
I was working on the user profile page of my app and I am allowing the user to change their email address. If the user email address is changed successfully, the data in the firebase database of the particular user will be updated. Also, After successfully changing the email address, firebase will send an email to the user's previous email address (the user email address before it was changed to the new one) asking if it was the actual owner of the account who changed the email address and there will be a link to reset their email. If the user chooses to reset the email (for whatever reason), the user's new email will be changed to the previous email. But the problem is that the data in the database will not be updated, how can I detect this change (email reset) and update the database?
authenticateUserAlert.addAction(UIAlertAction(title: "Done", style: .default, handler: { [weak authenticateUserAlert] (_) in
// Print the user email
let emailTextField = authenticateUserAlert?.textFields![0]
print("Email: \(emailTextField!.text!)")
// Print the user password
let passwordTextField = authenticateUserAlert?.textFields![1]
print("Password: \(passwordTextField!.text!)")
// Re-authenticate the user
let user = Auth.auth().currentUser
let credential = EmailAuthProvider.credential(withEmail: emailTextField!.text!, password: passwordTextField!.text!)
user?.reauthenticate(with: credential, completion: { (result, error) in
if error != nil {
// Alert: What ever the error
print(error!.localizedDescription)
Alerts.errorAlert(on: vc, error: error!.localizedDescription, dismissAlert: false)
} else {
print(result!)
let editProfilePage = EditUserProfile()
editProfilePage.updateUserInfo()
}
})
}))
Here is what I tried according to an answer
Auth.auth().currentUser?.reload(completion: { (Error) in
//Completion handler
if let email = Auth.auth().currentUser?.email {
UserDataRetrieval.userEmail = email
self.emailLabel.text = email
print(Auth.auth().currentUser?.email)
}
})
It depends on the type of authentication you are using but honestly you should just use the email that is part of the authenticated account and then you don't need to worry about updating it in the database.
You can always just get the users email by using Auth.auth().currentUser.email
Update
Found a workaround to the issue of the credential data, try using
Auth.auth().currentUser?.reload(completion: { (Error) in
if (Error != nil) {
//Do something with error
} else {
//Do something with success or do nothing
}
})
Just call update credentials at the start of the app if you want to always have to most up to date credentials
You can always build your own custom handler for the email change revocation landing page. In that landing page you can update your database.
Check the official docs on how to do that.
Having looked through lots of previous questions and looking on the Firebase website documentation, it keeps leading me back to the snippet of code I need in my VC, BUT not how to actually set it up?.
Firstly in the email address verification setup on Firebase
I've by mistake put my personal email address as the 'reply to' email - do I put my personal (not business) email in there/how would I change it? Apologies for any over the top censoring (not sure what is private and not)
Secondly in my SignUpViewController what do I put as the URL String and what do I put as my IOSBundleID? Many thanks!
To change the email go to Authentication and press templates. There you have some options for your mail.
Press the pen beside noreply#yourfirebase.firebaseapp.com.
There you will have a replay to line and you can change all those settings
This is all you need to register a new user :
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!) {
(user, error) in
if error != nil {
print(error.localizedDescripton)
}else {
print("registration successful")
}
}
To send confirmation email to user make a call after user is created and use this method :
func sendConfirmationEmail() {
// Here you check if user exist
if self.authUser != nil && !self.authUser!.isEmailVerified {
self.authUser!.sendEmailVerification(completion: { (error) in
// Send the email
})
}
else {
// ERROR
}
}
You could now call the second method after user been created and the user will get an email
Upon logging in I want my app to make a new field in the Firebase database with the child named after the username.
if let email = emailField.text, let pass = passwordField.text {
// Check if it's sign in or register
if isLogin {
// Sign in the user with Firebase
Auth.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.ref?.child(email).childByAutoId().setValue("1")
self.performSegue(withIdentifier: "goHome", sender: self)
print("yes")
}
When I try to do this, it gives me an error called SIGABART which I believe is associated with not having segues connected properly.
Yet if I delete this line:
self.ref?.child(email).childByAutoId().setValue("1")
or change the email field to a random string like "test", it works fine and appears in Firebase.
If I remember correctly, you can't use symbol # in nodes names. It's first problem. You can do it another, I think better, way:
You need to create user to ref like:
/users/uid from created FIRUser.
You can do it with next steps:
For example, your registration page will have 3 UITextFields: userEmail, userLogin and userPassword.
// *1* Create user
FIRAuth.auth()!.createUser(withEmail: userEmail.text!,
password: userPassword.text!)
{ user, error in
if error == nil {
// *2* Then log him in
FIRAuth.auth()!.signIn(withEmail: self.userEmail.text!,
password: self.userPassword.text!)
{ result in
// *3* Create new user in database, not in FIRAuth
let uid = (FIRAuth.auth()?.currentUser?.uid)!
let ref = FIRDatabase.database().reference(withPath: "someStartPart/users").child(uid)
ref.setValue(["uid": uid, "email": userEmail.text!, "login": userLogin.text!, "creationDate": String(describing: Date())])
self.performSegue(withIdentifier: "fromRegistrationToMainPage", sender: self)
}
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
Like this. Hope it helps.
Firebase Auth will not allow you to store such a value. You will need to save this into Firebase Database or another service. e.g. In the Firebase Database:
userRef.setValue("username123")
You should save the username value in the database. Something like this:
FIRdatabase.database().reference().child("yourchildname").updateChild(u)
(Im on my phone, so the call might not be EXACTLY like that, but should be very close)
Cheers.
Swift 4:
//***** for realTime database
let ref = Database.database().reference(fromURL: "https://add your project URL")
let userRef = ref.child("users").child(user.user.uid)
let values = ["Email": email, "UserName": userName] //userName is the name of textField
So far I can only find how to do this in the AWS documentation in objective c, not swift. I am successfully creating users in the User Pool in swift with the following code:
let userPool = AWSCognitoIdentityUserPool(forKey: "myApp")
var name = AWSCognitoIdentityUserAttributeType()
name.name = "name"
name.value = nameEntry.text
var phone = AWSCognitoIdentityUserAttributeType()
phone.name = "phone_number"
phone.value = "+1" + phoneNumberEntry.text!
var email = AWSCognitoIdentityUserAttributeType()
email.name = "email"
email.value = emailEntry.text
userPool.signUp("goats", password: passwordEntry.text!, userAttributes: [name, phone, email], validationData: nil)
Doing the above code creates a user in the Cognito User Pool as expected.
Furthermore, the above code successfully sends a verification code to the phone number provided. However, I have been unable to then successfully pass this verification code back to AWS and verify the phone number. I have tried both of the following lines after the user has been created in the User Pool, neither of which are changing the phone number to being verified:
user.verifyAttribute("phone_number", code: verificationEntry.text!)
user.confirmSignUp(verificationEntry.text!)
for what it's worth I am setting the user variable to the following, after the user has signed up:
self.user = userPool.getUser()
None of this is working and AWS's objective c documentation isn't helpful. Any ideas on how to verify the user's phone number?? Thanks
You should use userPool.getUser(username: String), not userPool.getUser().
In your case:
self.user = userPool.getUser(nameEntry.text)
Otherwise, you might get following error.
[Debug] AWSURLResponseSerialization.m line:63 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body:
{"__type":"InvalidParameterException","message":"2 validation errors detected: Value at 'username' failed to satisfy constraint: Member must have length greater than or equal to 1; Value at 'username' failed to satisfy constraint: Member must satisfy regular expression pattern: [\\p{L}\\p{M}\\p{S}\\p{N}\\p{P}]+"}
After signup, you should call confirm signup to confirm the user and mark the phone/email (where you got the code).
You can do get user to confirm whether the attribute was marked as verified.
P.S.: If you are having issues please PM me your user pool id, user name and signup time frame.
You need to specify the user to whom the verfication code was sent. So use getUser() with the username. Then you call confirmSignUp().
#IBAction func confirmButtonPressed(_ sender: AnyObject) {
if confirmationCodeTextField.text != nil {
let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
let user: AWSCognitoIdentityUser = pool.getUser("userName")
user.confirmSignUp(confirmationCodeTextField.text!).continue(with: AWSExecutor.mainThread(), withSuccessBlock: { (task: AWSTask<AWSCognitoIdentityUserConfirmSignUpResponse>) -> Any? in
if task.error != nil {
// Error
} else {
// handle the success response
}
return nil
})
} else {
// Ask user to enter the confirmation code.
}
}
The above method will help you to confirm the user sign up. While getting the user you must specify the "user Name". This code is written in swift 3.