Password Change Parse swift - ios

I have an app that allows a user to reset their password by putting their old one in a textfield and their new one in the next textfield. But in the old password textfield, the password they entered has to match the one that is registered to the currently logged in user. My app keeps crashing. Can someone help me. Here is the code. An image of the error is here.
if Password.text == (PFUser.current()?.password)! {
}else{
}

Try to add exclamation after the text: -
if Password.text! == (PFUser.current()?.password)! {
}else{
}
Edit: -
There is no way to get old password from Parse. Workaround though is.. you can first try authenticate user by giving the password which user has entered.. if authentication is successful then that means the entered old password is correct.. has been described here. Although it is android code it gives the required logic.
ParseUser.logInInBackground(ParseUser.getCurrentUser().getUsername(), currentPassword, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
// Hooray! The password is correct
} else {
// The password was incorrect
}
}
});

Related

Failure to login straight after verifying but successful on second tap

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.

Firebase Auth and Swift: Check if email already in database

I'm working on an iOS app which will use Firebase for user management (sign up, sign in, etc.)
I'm new to Firebase, but it's mostly going ok. I've connected it, I have created users and logged in, etc.
But, I'm trying to change my UI so that the "Sign up" button is initially hidden and will only appear when:
all fields are not empty
email address is valid (using regex)
email address in not already in the database
user name is not already in the database
password and confirmPassword fields are equal
I can't figure out #3 and #4.
I've been reading documentation, watching videos, chasing links all over StackO and beyond, but I can't figure it out.
Can anyone point me in the right direction?
If you are using email & password authentication, the solution is very simple.
Firebase Authentication will not allow duplicate emails so when the createUser function is executed, if the email already exists Firebase will return a emailAlreadyInUse error in the error parameter. You can then cast this to an NSError to see which one it is and handle appropriately.
So the function is like this
Auth.auth().createUser(withEmail: createEmail, password: password ) { user, error in
if let x = error {
let err = x as NSError
switch err.code {
case AuthErrorCode.wrongPassword.rawValue:
print("wrong password")
case AuthErrorCode.invalidEmail.rawValue:
print("invalid email")
case AuthErrorCode.accountExistsWithDifferentCredential.rawValue:
print("accountExistsWithDifferentCredential")
case AuthErrorCode.emailAlreadyInUse.rawValue: //<- Your Error
print("email is alreay in use")
default:
print("unknown error: \(err.localizedDescription)")
}
//return
} else {
//continue to app
}
I threw some random errors into that case statement but check the link for a complete list of all AuthErrorCodes.
You can also do this
Auth.auth().fetchSignInMethods(forEmail: user, completion: { (signInMethods, error) in
print(signInMethods)
})
I think you can check it by using this method
let ref1 = Database.database().reference().child("Users").queryOrdered(byChild: "UserName").queryEqual(toValue: "UserName enter by user")
ref1.observeSingleEvent(of: .value) { (sanpshot) in
print(sanpshot.exists()) // it will return true or false
}
and same for email.

Update a User's Firebase password in Swift

I have a UITableViewController and I'd like the user to be able to change their current password with a new one.
The view is very straight forward - 2 UITextFields where I'd like them to enter their current password and another one for their desired new password.
The problem is I cannot find in Firebase's documentation a method that does that. Does anyone have an idea how to accomplish this?
PS: Ignore that it says "Update your email", this will be fixed.
1. Change Password
In Order to change password for Firebase User you do not need old password. You can do it by re-authenticating user and then updating password.
i. Re-authenticate User:
let user = Auth.auth().currentUser
var credential: AuthCredential
// Prompt the user to re-provide their sign-in credentials
user?.reauthenticate(with: credential) { error in
if let error = error {
// An error happened.
} else {
// User re-authenticated.
}
}
https://firebase.google.com/docs/auth/ios/manage-users#re-authenticate_a_user
ii. Change Password
Once user is re-authenticated use following method to Change password:
Auth.auth().currentUser?.updatePassword(to: password) { (error) in
// ...
}
2. Forgot Password
To handle this case you can send password reset link to user's email. Use following method:
Auth.auth().sendPasswordReset(withEmail: email) { error in
// ...
}
source: https://firebase.google.com/docs/auth/ios/manage-users

"provideCredentialWithoutUserInteractionForIdentity:" is not working

I have an app that autofills the password on iOS 12. Now I want to implement this function:
- (void)provideCredentialWithoutUserInteractionForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity;
But I cant get it to work like it should.
AutoFill is enabled in settings and also enabled for my app.
I've read the documentation but this doens't help me. https://developer.apple.com/documentation/authenticationservices/ascredentialproviderviewcontroller/2977554-providecredentialwithoutuserinte?language=objc
I've tried calling this function from viewDidLoad, prepareCredentialListForServiceIdentifiers,.. but this is stupid and definitely won't work.
- (void)provideCredentialWithoutUserInteractionForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity {
ASPasswordCredential *credential = [[ASPasswordCredential alloc] initWithUser:#"theUsername" password:#"thePassword"];
[self.extensionContext completeRequestWithSelectedCredential:credential completionHandler:nil];
}
The function should show the credentials above the keyboard, but this doesn't happen. It just shows the default "Passwords" button.
Make sure you have some ASPasswordCredentialIdentitys for your domain/url in ASCredentialIdentityStore. (These are records with some unique recordIdentifier, that doesn't hold password but hold data that can help you decide what password you should take from some secure storage of your choice.)
When you open a website, iOS looks up the ASCredentialIdentityStore, and shows a big button for quick login if there's a matching record. If you hit the button - this is only when provideCredentialWithoutUserInteraction callback is executed. Your task is to work with ASPasswordCredentialIdentity passed as an argument (it has recordIdentifier field) and find matching password for it (in your database/keychain/etc.) When you have password - you create ASPasswordCredential and pass it to self.extensionContext.completeRequest. Also make sure to call extensionContext.cancelRequest in case of any errors.
here's my example
override func provideCredentialWithoutUserInteraction(for credentialIdentity: ASPasswordCredentialIdentity) {
let databaseIsUnlocked = false
if (databaseIsUnlocked) {
// this function queries my custom keychain records by recordIdentifier (Generic Passwords) to find matching password
getItemForRecordId(identifier: credentialIdentity.recordIdentifier) { password, err in
guard password != nil else {
print("password was nil")
self.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code:ASExtensionError.userInteractionRequired.rawValue))
return;
}
let passwordCredential = ASPasswordCredential(user: credentialIdentity.user, password: password as! String);
self.extensionContext.completeRequest(withSelectedCredential: passwordCredential, completionHandler: nil);
};
} else {
self.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code:ASExtensionError.userInteractionRequired.rawValue))
}
}

How to set up Firebase iOS authentication email

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

Resources