Dealing with Email address already in use - Firebase Authentication - firebase

My app has gmail and facebook authentication integrated through Firebase. I noticed if someone signs up with their gmail then signs up with Facebook, if the Facebook had the same email as their gmail then they'll get the error:
"The email address is already in use by another account."
Is the only reasonable way to handle this to tell the user to sign in with different credentials? Maybe show a message like "Email already in use, please sign up with different account"?

There are 3 ways in which you can handle this problem.
The first one is to verify if the email address exists and then display a message. This is exactly what you said. The message is up to you.
The second approach is to enable users to have multiple accounts per email address. In other words, if a user signs up with Gmail and then signs up with Facebook and he has the same email address then he ends up having 2 different accounts. A single email address, 2 different accounts This is not a good practice but according to your needs, you can even use it.
The third approach is to have only one account per email address. This means that you are preventing the users from creating multiple accounts using the same email address with different authentication providers. This is a common practice and also the default rule in the Firebase console. This means, that you'll want to implement later another kind of authentication with another provider, and it will follow the same rule. In this case, will have a single email address with a single account.
To enable or disable this option, go to your Firebase console, choose Authentication, select the SIGN-IN METHOD tab, and at the bottom of your page you'll find the Advanced section.

It happened to me and it was because I was calling the method wrong.
use signInWithEmailAndPassword

Since there are a lot of similar questions to this topic I am posting my method for this error since I did not find an answer that suits a specific situation.
Lets say you have enabled an E-Mail login and also a Facebook login and a user registers via email login first and then tries to login with Facebook with the same email. Now, if you don't want to link this account with the existing one, or don't want to enable multiple accounts with one email, you can just add a Toast message that will notify the user that the email is already in use. And he cannot login via Facebook then. Here is my approach that handles the error when a user tries to register via Facebook with an already existing email:
private void handleFacebookAccessToken(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
FirebaseUser user = mAuth.getCurrentUser();
getTokenId();
updateUI(user);
} else {
Toast.makeText(SignInActivity.this, "Your Facebook email is already in use.", Toast.LENGTH_LONG).show();
}
}
});
}
I basically used the code provided by Firebase and added and if-else statement (if (task.isSuccessful())
Hope it will help someone!

void createuser(String email, String password) async {
try{
await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
}
on FirebaseAuthException catch (e){
if(e.code == "email-already-in-use"){
Get.showSnackbar(const GetSnackBar(
margin: EdgeInsets.all(15),
borderRadius: 8,
message:
('There already exists an account with the given email address.'),
duration: Duration(seconds: 3),
backgroundColor: Colors.red,
));
}
}
}
Here is an example for the 'email-already-in-use' firebase authentication error.

Related

Where does Firebase store whether the user is email validated or not

Despite spending an entire afternoon searching SO and Google I can't seem to find the answer to this question - which makes me think I'm doing something wrong.
I have setup an email authentication script, where Firebase sends the email to the user for them to verify their email address. This works fine. The link in the email seems to work, and displays a page saying you are now verified.
So far so good - BUT where does Firebase store whether the user is email validated or not?
I assumed this would be in the Authentication screen. It shows the users but no where does it show whether the user is email validated or not .... just the standard 5 columns for an Email and Password based user (Identifier, Provider, Created, Signed In and UID) but nowhere is there an option for whether that user is email validated??
It's not visible in the Firebase console. But you can access this programmatically in your Flutter app in the User object with the emailVerified property.
The User class from FirebaseAuth contains a property called emailVerified, which you can read to know if the user has verified her/his email or not:
final FirebaseAuth _auth = FirebaseAuth.instance;
User _user = await _auth.signInWithEmailAndPassword(email: _email, password: _password);
if (_user.emailVerified) {
print('The user verified the email address');
} else {
print('The user has not verified the email address yet');
}

Firebase auth: update lost phone number

When a user has lost their phone number, and they want to update their account with a new phone number, what would be the best path to follow? We already have their email.
The problem is Firebase needs to send an SMS to the old phone number before updating it, which the user has lost.
My best idea so far is to authenticate them with their email, then send a request to our backend with the new phone number they entered, and then use the Firebase Admin SDK to update the user's phone number. There's just one problem here: How would I verify this new phone number, to make sure the user didn't just add some random one?
I'm answering my own question with the path that I followed:
First, we get their email and send a verification email, which contains a button that redirect to a deeplink that contains a token that we use on the backend to verify that the user indeed is who they claim to be.
After the user clicks the link, we show a screen on the app that asks for the new phone number.
After the new phone number is entered, we send it to our backend, along with the token on the deeplink. We verify the token, then use Twilio to send a verification SMS to this new number.
In the meantime, the user has already been sent to the verification code screen. They get the Twilio SMS and put in the code. We send this code to our backend and make sure the code they entered is correct.
If the code is correct, we use the Firebase Admin API to update this user's phone number to the new one.
Firebase has a method for phone authentication
For Android: https://firebase.google.com/docs/auth/android/phone-auth?authuser=0#send-a-verification-code-to-the-users-phone
For Web: https://firebase.google.com/docs/auth/web/phone-auth#send-a-verification-code-to-the-users-phone
For IOS: https://firebase.google.com/docs/auth/ios/phone-auth?authuser=0#send-a-verification-code-to-the-users-phone
Edit
The way to change a user's phone number is through the method below
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.updatePhoneNumber(credentials)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
}
}
});
The problem is you need to send a verification code to the user's old phone number (Links above) to create a PhoneAuthCredential (reference).
I do not know a way around that using firebase

How to get firebase authentification linking account working with Unity?

I want to provide users multiple authentification providers with phone, facebook and a simple email and password.
the thing is, i want the same account to be provided (same user id, same display name) if the account is linked with the same Email address.
as i got to understand it through the documentation, you can do it if the user connects and link an account when already connected with another provider.
so my question is : is there anyway to do it automatically, when let's say, the user connects with another provider next time, without having to tell him to link it himself.
[Edit - after further investigation, I found a better answer]
It turns out that only allowing the email address once comes with some caveats - that are really well laid out in this GitHub issue but I'll try to summarize.
You can have an unverified account, which may allow you to register over it (the user hasn't proved that they own the account).
Next are kind of the social identity providers. Facebook is assumed to have verified your email once (for example), so you may get a duplicate account exception.
Finally, there are email identity providers - these are seen as authoritative for all email addresses that they're associated with and will overwrite any account with the same address for the domains that they're authoritative over. Both Google and Apple sign ins have this control over their respective domains for example.
See this section of the web documentation and this and this stack overflow answers.
At this point, you may be wondering how to get more control over the process if this isn't the user flow you want.
You may opt to make a call to FirebaseAuth.DefaultInstance.FetchProvidersForEmailAsync before allowing the user to log in. Then you can choose to prompt them to log back in with their existing account first to link accounts before creating a new one (and potentially replacing the old account). For example:
public async void LogIn(string email, Credential credential) {
var auth = FirebaseAuth.DefaultInstance;
var identityProviders = await auth.FetchProvidersForEmail(email);
if (identityProviders.Empty()) {
var user = auth.SignInWithCredentialAsync(credential);
}
else {
// somewhere in here, log in the user and call
// user.LinkWithCredentialAsync(credential)
DisplayLinkAccountDialog(identityProviders, email, credential);
}
}
[Old answer - information still applicable but incomplete]
By default, Firebase authentication only allows one email address per user. See this section at the bottom of your Authentication Providers page in the Firebase console:
So when you sign up a new user, you should get a FirebaseException with the error code AccountExistsWithDifferentCredentials.
To handle this, you'd make your continuation look something like:
/* Registration call */.ContinueWithOnMainThread(task=>{
if (task.Exception) {
foreach (var e in task.Exception.InnerExceptions) {
var fe = e as FirebaseException;
if (fe != null) {
if (fe.ErrorCode == AuthError.AccountExistsWithDifferentCredentials) {
TryToLinkInsteadOfCreateAccount(); // TODO - cache credentials and implement this
}
}
}
}
});
Let me know if that helps!
--Patrick

Is there any way to get firebase Auth UID without login?

What i want to know is without login get Auth User UID from firebase
that already registered user
I already read firebase document but all the explain focus on when user logged only at that time can get UID...
but i just want to get UID and user email address without login situation
Is there any way?
Nope, there is no way using firebase authentication to retrieve the uid or email is the user is currently not logged in.
The only other way to actually retrieve them, is to use firebase database. So, when the user registers in your application, you also send the data of the user to the database and then you will be able to retrieve the data later on even if he is not logged in.
For example (on register) you can send this data to the database:
users
userId
email : email_here
name : name_here
Your question is not clear.
You can create the user via the Admin SDK if you know the user's credentials. You can also lookup an existing user's information by email or uid with the Admin SDK.
Learn more about this from the official docs.
You can apply a trick to do this. Though this is not an optimal solution.
One thing you have to remember that, "There is no way to get a UID without login".
Create a dummy user from your backend with a dummy email and password.
Send the email and password from the backend to your client-side app. You can always hash the password if you want to give an extra security layer.
Now call signInWithEmailAndPassword function from firebase SDK and provide email and password which came from the backend.
The user is already registered in the backend, so now you can get the UID from your client app.
mAuth.signInAnonymously()
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInAnonymously:success");
FirebaseUser user = mAuth.getCurrentUser();
Log.d("userstatus","user id is "+user.getUid());
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInAnonymously:failure", task.getException());
}
// ...
}
});

Firebase fails to send password reset email from console

The existing user has trouble signing in and wants to reset the password. She doesn’t receive any reset password emails. We also tried to send the reset email through Firebase Console but no luck - no emails got delivered.
Is there any way to set a password manually through Firebase console or any other workaround?
Thanks!
You can set the user's password through Firebase's Admin SDKs. These SDKs run with administrative privileges, so should only be run in a trusted environment such as your development machine, a server you control, or Cloud Functions.
This is an example of setting a user's password with Node.js:
admin.auth().updateUser(uid, { password: "newPassword" })
For more samples (including in other supported languages), see the documentation on updating a user profile.
Firebase Admin SDK sounds like a good option
Check SMTP settings in the reset mail template
De-hash password manually :)
Issue got resolved. SendGrid (service that Firebase uses to send emails) had some maintenance during 8 hours in Asia region (my user is from Asia region) that's why it was working for me and not working for her.
Check SendGrid status URL: http://status.sendgrid.com
Thanks for all your suggestions!
You can set a user's password with the updatePassword method and send "SOME-SECURE-PASSWORD" :)
For example:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String newPassword = "SOME-SECURE-PASSWORD";
user.updatePassword(newPassword)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User password updated.");
}
}
});
Documentation is here

Resources