Change password of firebase user in flutter - firebase

I want to change the password of a firebase account. To do that the user should enter the old password before. If it is correct then he is allowed to change pass. I used this code which is only for changing the pass and not comparing the old one.
void _changePassword(String password) async{
//Create an instance of the current user.
FirebaseUser user = await FirebaseAuth.instance.currentUser();
//Pass in the password to updatePassword.
user.updatePassword(password).then((_){
print("Successfully changed password");
}).catchError((error){
print("Password can't be changed" + error.toString());
//This might happen, when the wrong password is in, the user isn't found, or if the user hasn't logged in recently.
});
}

The idea is to verify old password by resigning in user using firebaseAuth, you can get user email by passing user.email to string, and let user input old password. If sign in proccess failed, password change shouldn't happen.
void _changePassword(String password) async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String email = user.email;
//Create field for user to input old password
//pass the password here
String password = "password";
String newPassword = "password";
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
user.updatePassword(newPassword).then((_){
print("Successfully changed password");
}).catchError((error){
print("Password can't be changed" + error.toString());
//This might happen, when the wrong password is in, the user isn't found, or if the user hasn't logged in recently.
});
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}

it will not allow you to verify its previous or old password . it will directly send email for forgot and there you need to add your new password . and and you have to back again to application and your password will be updated as you wil try to login .

If the user hasn't signed in recently, Firebase will automatically require them to reauthenticate before they can change their password (or perform other sensitive operations). So you typically should only require the user to reauthenticate when Firebase tells you to.
When that happens, follow the steps in the documentation on reauthenticating a user.

Related

what are the error codes for Flutter Firebase Auth Exception?

I have tried to read this thread List of Authorisation errors with Firebase login , and also I have tried to search, but I just can find admin SDK authentication error in here here
those error code from those links are different from the error code for Firebase Auth for Flutter app
I mean, I need the error codes in here
Future<void> signInUsingEmail({required String email, required String password}) async {
try {
await _auth.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (error) {
// I need the error.code in here
print(error.code);
}
could I know all available error codes? so I can write my own error message in my own language. as for now, I can only catch these error codes below
"too-many-requests"
"wrong-password"
"network-request-failed"
what else?
For the signInWithEmailAndPassword method for Flutter, you will find the error codes in the firebase_auth package documentation.
They are actually the same than the JS SDK ones: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#error-codes_12
For anyone that does not like clicking on links:
signInWithEmailAndPassword
wrong-password: Thrown if the password is invalid for the given email, or the account corresponding to the email doesn't have a password set.
invalid-email: Thrown if the email address is not valid.
user-disabled: Thrown if the user corresponding to the given email has been disabled.
user-not-found: Thrown if there is no user corresponding to the given email.
createUserWithEmailAndPassword
email-already-in-use: Thrown if there already exists an account with the given email address.
invalid-email: Thrown if the email address is not valid.
operation-not-allowed: Thrown if email/password accounts are not enabled. Enable email/password accounts in the Firebase Console, under the Auth tab.
weak-password: Thrown if the password is not strong enough.
signInWithCredential
account-exists-with-different-credential: Thrown if there already exists an account with the email address asserted by the credential. Resolve this by calling fetchSignInMethodsForEmail and then asking the user to sign in using one of the returned providers. Once the user is signed in, the original credential can be linked to the user with linkWithCredential.
invalid-credential: Thrown if the credential is malformed or has expired.
operation-not-allowed: Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab.
user-disabled: Thrown if the user corresponding to the given credential has been disabled.
user-not-found: Thrown if signing in with a credential from EmailAuthProvider.credential and there is no user corresponding to the given email.
wrong-password: Thrown if signing in with a credential from EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set.
invalid-verification-code: Thrown if the credential is a PhoneAuthProvider.credential and the verification code of the credential is not valid.
invalid-verification-id: Thrown if the credential is a PhoneAuthProvider.credential and the verification ID of the credential is not valid.id.
reauthenticateWithCredential
user-mismatch: Thrown if the credential given does not correspond to the user.
user-not-found: Thrown if the credential given does not correspond to any existing user.
invalid-credential: Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
invalid-email: Thrown if the email used in a EmailAuthProvider.credential is invalid.
wrong-password: Thrown if the password used in a EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password.
invalid-verification-code: Thrown if the credential is a PhoneAuthProvider.credential and the verification code of the credential is not valid.
invalid-verification-id: Thrown if the credential is a PhoneAuthProvider.credential and the verification ID of the credential is not valid.
signInWithAuthProvider
user-disabled: Thrown if the user corresponding to the given email has been disabled.
signInAnonymously
operation-not-allowed: Thrown if anonymous accounts are not enabled. Enable anonymous accounts in the Firebase Console, under the Auth tab.
signInWithEmailLink
expired-action-code: Thrown if OTP in email link expires.
invalid-email: Thrown if the email address is not valid.
user-disabled: Thrown if the user corresponding to the given email has been disabled.
So I created this gist
And it's basically a handler for some common firebase auth exceptions.
This is an example on how to use it
Future createUser(String email, String password) async {
try {
UserCredential customUserCredential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: email, password: password);
return customUserCredential.user!.uid;
} on FirebaseAuthException catch (authError) {
throw CustomAuthException(authError.code, authError.message!);
} catch (e) {
throw CustomException(errorMessage: "Unknown Error");
}
TextButton(
onPressed: () async {
try {
//final user = FirebaseAuth.instance.currentUser;
final email = _emailController.text;
final password = _passwordController.text;
// await FirebaseAuth.instance // final userCredential =
// .signInWithEmailAndPassword(
// email: email, password: password);
AuthService.firebase()
.logIn(email: email, password: password);
final user = AuthService.firebase().currentUser;
if (user?.isEmailVerified ?? false) {
Navigator.of(context).pushNamedAndRemoveUntil(
emailRoute, (route) => false);
} else {
Navigator.of(context)
.pushNamedAndRemoveUntil(noteRoute, (route) => false);
}
//devtools.log(userCredential.toString());
//This line of text may not work to print data
// print(userCredential.toString());
} on FirebaseAuthException catch (e) {
if (e.code == 'network-request-failed') {
showErrorDialog(context, 'No Internet Connection');
//devtools.log('No Internet Connection');
} else if (e.code == "wrong-password") {
return showErrorDialog(
context, 'Please Enter correct password');
//devtools.log('Please Enter correct password');
//print('Please Enter correct password');
} else if (e.code == 'user-not-found') {
showErrorDialog(context, 'Email not found');
// print('Email not found');
} else if (e.code == 'too-many-requests') {
return showErrorDialog(
context, 'Too many attempts please try later');
//print('Too many attempts please try later');
} else if (e.code == 'unknwon') {
showErrorDialog(
context, 'Email and password field are required');
//print('Email and password field are required');
} else if (e.code == 'unknown') {
showErrorDialog(
context, 'Email and Password Fields are required');
//print(e.code);
} else {
print(e.code);
}
}
},
child: const Text('Login')),

Flutter Change password of firebase user is not working

I'm trying to implement change password for firebase user.
handleChangePassword(BuildContext parentContext) {
return showDialog(
context: parentContext,
builder: (_) {
return ChangePasswordPopUp(
currentEmail: widget.email,
auth: widget.auth,
newPassword: (val) async {
await widget.auth.changePassword(val);
},
);
});
}
The user gets reauthenticated in ChangePasswordPopUpand with ValueChanged newPassword I'm calling changePassword
Future<void> changePassword(String password) async {
FirebaseUser user = await _firebaseAuth.currentUser();
print(password);
user.updatePassword(password).then((_){
print("Succesfull changed password");
}).catchError((error){
print("Password can't be changed" + error.toString());
});
}
It prints the choosen new password and "Successful changes password" so everything should be fine but when I'm trying to logout and login again it is the old password which works and not the new one.
Any suggestions?
void _changePassword(String password) async{
//Create an instance of the current user.
FirebaseUser user = await FirebaseAuth.instance.currentUser();
//Pass in the password to updatePassword.
user.updatePassword(password).then((_){
print("Your password changed Succesfully ");
}).catchError((err){
print("You can't change the Password" + err.toString());
//This might happen, when the wrong password is in, the user isn't found, or if the user hasn't logged in recently.
});
}

How to check the particular field in the firestore after authentication in flutter?

I have a field in firestore "isEnabled" it contains boolean value. So if it is equal to true then the user login to the app he prompted to the home page.
If the field "isEnabled" is equal to false then a message should be displayed your account is disabled.
For now I am able to do login and after that the field is checked and if it is false the user is logged out.
Is there any way in which first authentication takes place, then the user is taken to a page where it shows "Checking few more details.." kind of a loading page and if the "isEnabled" field is false it will show your account has been disabled.
I tried doing the checking of the field before but it's not possible and after
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
As soon as the above line is executed the user is obviously prompted to the home page.
What I am able to achieve that code is shown below -
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
print(user.uid);
final firestore = Firestore.instance;
/*
retrieving the fields from the database for checking the isEnabled field
*/
await firestore.collection("admins").document(user.uid).get().then((resp) {
logoutToast();
if ((resp.data["isEnabled"]) == false) {
disableToast();
signOut();
} else {
loginToast();
}
return user;
});
//print(qn);
//return user;
} catch (error) {
print(error.toString());
return null;
}
}
Thanks !!
You can always disable a user in Firebase Auth and he won't be able to login at all.
If you still want to go your way and check a isEnabled on Firebase Firestore, than make the login and DON'T direct the user to the Home Screen, instead direct him to a Verification Screen and if isEnabled is true he goes to the Home Screen, if it's false you log him out.
Another solution is to have a Dialog shown in the Home Screen after the first time it's displayed and that Dialog will run the verification logic.

Get Identifier field from Firebase Auth Console

I'm trying to get the email from the user that's currently authenticated using the Facebook Firebase provider. The email is listed under the Identifier field inside the Project's Firebase Authentication Console:
However when I invoke firebase.auth().currentUser the user information loads, however the email field is null. Any ideas on how to get the Identifier (which is where I see the email address) from Firebase? Is this even possible?
Below is the code I'm using:
componentDidMount() {
let user = firebase.auth().currentUser;
let name, email, photoUrl, uid, emailVerified;
if (user !== null) {
name = user.displayName;
email = user.email;
photoUrl = user.photoURL;
emailVerified = user.emailVerified;
uid = user.uid;
console.log(name, email, photoUrl, emailVerified, uid);
}
}
Note: Prevent creation of multiple accounts with the same email address is enabled in Firebase. Also, Facebook API permissions are set to ['public_profile', 'email']
After some testing and debugging I found that the email field will be populated if you're using a regular Firebase Email/Password Sign In method. However, if you're using another Sign In provider method such as Facebook, the email field will appear null (not sure why).
Further inspection of the user object revealed a providerData property.
It's an array that contains all the provider information (including the email address):
So, I updated my code to accommodate this:
componentDidMount() {
let user = firebase.auth().currentUser;
let name, email, photoUrl, uid, emailVerified;
if (user) {
name = user.displayName;
email = user.email;
photoUrl = user.photoURL;
emailVerified = user.emailVerified;
uid = user.uid;
if (!email) {
email = user.providerData[0].email;
}
console.log(name, email, photoUrl, emailVerified, uid);
}
}
In my case, the getEmail() method always returns data for three sign-in possibilities (if user gave authorization to my app to show/use email): Sign in with Email, Sign in with Google, Sign in with Facebook.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
Log.v(TAG,"user.getEmail():"+user.getEmail());
if (user.getEmail() == null){
// User did not authorize the app to show/user email
}
else {
Log.v(TAG,"user.getEmail():"+user.getEmail());
}

Firebase confirmation email not being sent

I've set up Firebase email/password authentication successfully, but for security reasons I want the user to confirm her/his email.
It says on Firebases website:
When a user signs up using an email address and password, a confirmation email is sent to verify their email address.
But when I sign up, I doesn't receive a confirmation email.
I've looked and can only find a code for sending the password reset email, but not a code for sending the email confirmation.
I've looked here:
https://firebase.google.com/docs/auth/ios/manage-users#send_a_password_reset_email
anyone got a clue about how I can do it?
I noticed that the new Firebase email authentication docs is not properly documented.
firebase.auth().onAuthStateChanged(function(user) {
user.sendEmailVerification();
});
Do note that:
You can only send email verification to users object whom you created using Email&Password method createUserWithEmailAndPassword
Only after you signed users into authenticated state, Firebase will return a promise of the auth object.
The old onAuth method has been changed to onAuthStateChanged.
To check if email is verified:
firebase.auth().onAuthStateChanged(function(user) {
if (user.emailVerified) {
console.log('Email is verified');
}
else {
console.log('Email is not verified');
}
});
After creating a user a User object is returned, where you can check if the user's email has been verified or not.
When a user has not been verified you can trigger the sendEmailVerification method on the user object itself.
firebase.auth()
.createUserWithEmailAndPassword(email, password)
.then(function(user){
if(user && user.emailVerified === false){
user.sendEmailVerification().then(function(){
console.log("email verification sent to user");
});
}
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
});
You can also check by listening to the AuthState, the problem with the following method is, that with each new session (by refreshing the page),
a new email is sent.
firebase.auth().onAuthStateChanged(function(user) {
user.sendEmailVerification();
});
The confirmation email could be in your spam folder.
Check your spam folder.
You can send verification email and check if was verified as follow into the AuthListener:
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
//---- HERE YOU CHECK IF EMAIL IS VERIFIED
if (user.isEmailVerified()) {
Toast.makeText(LoginActivity.this,"You are in =)",Toast.LENGTH_LONG).show();
}
else {
//---- HERE YOU SEND THE EMAIL
user.sendEmailVerification();
Toast.makeText(LoginActivity.this,"Check your email first...",Toast.LENGTH_LONG).show();
}
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// [START_EXCLUDE]
updateUI(user);
// [END_EXCLUDE]
}
};
if you're using compile "com.google.firebase:firebase-auth:9.2.0" and
compile 'com.google.firebase:firebase-core:9.2.0' the method sendEmailVerification() will not be resolved until you update to 9.8.0 or higher. It wasted most of time before I figured it out.
I have been looking at this too. It seems like firebase have changed the way you send the verification. for me
user.sendEmailVerification()
did not work.
If you get an error such as user.sendEmailVerification() doesn't exist.
use the following.
firebase.auth().currentUser.sendEmailVerification()
It's not the answer to the question but might help someone.
Don't forget to add your site domain to the Authorised domains list under Sign-in-method
You could send a verification email to any user whose email is linked to the Firebase Auth account. For example, in Flutter you could do. something like :
Future<void> signInWithCredentialAndLinkDetails(AuthCredential authCredential,
String email, String password) async {
// Here authCredential is from Phone Auth
_auth.signInWithCredential(authCredential).then((authResult) async {
if (authResult.user != null) {
var emailAuthCredential = EmailAuthProvider.getCredential(
email: email,
password: password,
);
authResult.user
.linkWithCredential(emailAuthCredential)
.then((authResult,onError:(){/* Error Logic */}) async {
if (authResult.user != null) {
await authResult.user.sendEmailVerification().then((_) {
debugPrint('verification email send');
}, onError: () {
debugPrint('email verification failed.');
});
}
});
}
});
}

Resources