Firebase auth: update lost phone number - firebase

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

Related

Creating a user with email and password(both at the same time) Firebase Flutter

I need to store the phone number, email, and name of the user.
Sign up screen has 4 TextFields 1.Mobile, 2.Email, 3.Name, 4.Password
I can create an account with createUserWithEmailAndPassword, but I've no idea about storing the phone number of a user. Do I need to set up phone verification? if so how can I store the email of the user and how to set up a phoneVerification method.
Simply question is how to store the email, and phone number of a user at the same time
first signup the user with email and password;
after signing up with email and also signing in use FirebaseAuth.instance.verifyPhoneNumber method to start the phone verification process;
see this medium post : Firebase phone auth with flutter(latest update);
also, read the comments in the dart file where the method verifyPhoneNumber exists;

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());
}
// ...
}
});

How to update phone number of a auth account by facebook provider

I have already authenticated with facebook provider in firebase. After authentication, I get back a user object with user details like name, email, and phoneNumber. The requirement is that I need to update phoneNumber as phone number I get back in user object is null. The phone number is crucial to the app I am building. There is this one option where I first authenticate the user with facebook provider and go to next screen and ask the user for a phone number and authenticate again with a phone number which basically creates a new user with phone number auth provider of the firebase after all this link account created by using facebook auth provider and phone number auth provider, but this method is kind of weird and kind of lot of work to be done just to store user's phone number, is there any other kind of method out there that I am missing? I really need to store user phone number and verify it but need to use facebook provider as the main authentication method.
I am using React Native (Expo) to build the mobile app.
The thing that I have already done, which has not worked for me.
let user = auth.currentUser;
user
.updateProfile({phoneNumber: <PhoneNumberInputFromUser>})
.then(() => {
this.navigateToMapView();
})
.catch(error => {
// TODO: Handle errors
console.log(error);
});
Using this does not throw error nor updates phoneNumber. But another weird thing here is that it goes to the then section of the code and navigates to map view.
I assume you are setting the Facebook phone number as the firebase user phone number. To securely do this:
On your server, use the facebook user's access token to query the facebook api for that user's phone number.
Assuming you know the corresponding Firebase user's uid:
admin.auth().updateUser(facebookUserFirebaseUid, {phoneNumber: facebookPhoneNumber})
.then(function(userRecord) {
// Return response to client to reload the user to pick up the changes.
})
.catch(function(error) {
// Error occurred.
});

Proper way to verify user's mobile number using Firebase

I know that I can use Firebase's phone verification on Android and iOS, but the problem is that the information about client's verification can easily be forged on the client side, because I using only server side SSL certificate, so, only client knows that the server is trusted.
So, I decided to send mobile number on the server-side and check it there: send verification code and ask this verification code from the user. But I can't see any C++ server Firebase SDK, only client-side C++ SDK is available.
So, I have two options:
Understand how is client-side verification can be trusted on the server-side(note that I can have untrusted clients)? So, it's means I could use main Firebase phone number auth method.
Use server-side phone verification.
Please, help me with this misunderstanding in the Firebase.
Client side absolutely works here. The flow is like this:
You request a sign in using a phone number
The Firebase Phone Auth server sends a code to that number
The user enters your code into your app, which sends it to the Firebase Auth server
The Firebase Auth server returns you a Firebase Auth token
This works because a malicious user could only know the code if they had your phone. It doesn't guarantee the device is the one with that phone number (the user could have two phones, or sign in with a phone on a laptop), but it does verify the user has access to that number.
For verifying that to your own backend, you retrieve a Firebase ID token. This is just a little bundle of base64 encoded JSON, but importantly its cryptographically signed by Firebase. This means on your server you can verify that it was really created by Firebase, for the user and phone number that is contained within it. A user couldn't generate one of those tokens without access to the underlying account.
See the docs on verifying ID tokens for more!
So your next steps would be:
Retrieve the Firebase ID token
You can do this any time you're signed in.
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
Verify on server the contents of the ID token.
The admin SDKs are set up out of the box to check for the right certificate, audience, expiry, and other important properties of an ID token.
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error
});
decodedToken will contain properties for the phone number too!

Dealing with Email address already in use - Firebase Authentication

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.

Resources