Firebase Authentication using a Phone Number
Introduction to Firebase Authentication
Firebase is a secure and real-time database for Mobile (Android & iOS) and Web applications. Firebase offers backend services for your application. It provides authentication using password, phone numbers, Google, Facebook and Twitter and more. You may have seen Phone number authentication in many apps. You can use Firebase to sign in a user by sending SMS message i.e. OTP to the user’s phone.
Benefits of Phone number Authentication:
a) Authenticate identity: Phone verification helps to authenticate identity of user.
b) Prohibiting dummy users: Phone number authentication prevents duplication of accounts.
Why Phone number Authentication:
Firebase provides phone number authentication for free up to 10,000 SMS verification per month. It is enough for starter apps.
Before wasting a time let’s begin with Tutorial.

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android"
xmlns:app=”http://schemas.android.com/apk/res-auto"
xmlns:tools=”http://schemas.android.com/tools"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
tools:context=”.LoginActivity”>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”64dp”
android:orientation=”vertical”
android:padding=”16dp”>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:orientation=”horizontal”>
<Spinner
android:id=”@+id/mobile_country”
android:layout_width=”96dp”
android:layout_height=”56dp”
style=”@style/Base.Widget.AppCompat.Spinner.Underlined”
android:entries=”@array/str_array_country_code”/>
<EditText
android:id=”@+id/mobile_number”
android:layout_width=”match_parent”
android:layout_height=”56dp”
android:hint=”@string/str_mobile”
android:inputType=”phone”
android:textSize=”16sp”
android:maxLength=”10"/>
</LinearLayout>
<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”8dp”
android:orientation=”vertical”>
<TextView
android:id=”@+id/mobile_otp_message”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”@string/str_otp_text”
android:textSize=”16sp”
android:layout_marginBottom=”8dp”
android:visibility=”gone”/>
<EditText
android:id=”@+id/mobile_code”
android:layout_width=”match_parent”
android:layout_height=”56dp”
android:hint=”@string/str_verification_code”
android:inputType=”number”
android:textSize=”16sp”
android:maxLength=”6"
android:textAlignment=”center”
android:visibility=”gone”/>
</LinearLayout>
</LinearLayout>
<Button
android:id=”@+id/mobile_code_button”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:textAllCaps=”false”
android:text=”@string/str_button_next”
style=”@style/Widget.AppCompat.Button.Colored”
android:layout_alignParentBottom=”true”
android:layout_marginLeft=”24dp”
android:layout_marginRight=”24dp”/>
<Button
android:id=”@+id/mobile_login_button”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:textAllCaps=”false”
android:text=”@string/str_button_verify”
style=”@style/Widget.AppCompat.Button.Colored”
android:layout_alignParentBottom=”true”
android:layout_marginLeft=”24dp”
android:layout_marginRight=”24dp”
android:visibility=”gone”/>
</RelativeLayout>
LoginActivity.java
- How to send verification on User’s phone number
private void sendVerificationNumber(String mMobileNumber) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
mMobileNumber, // Phone number to verify with coutry code
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
}
verifyPhoneNumber() method is used to send verification code to the user.
2) Verification callbacks
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
}
@Override
public void onVerificationFailed(FirebaseException e) {
}
@Override
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) {
mVerificationId = verificationId;
mResendToken = token;
}
};
- onVerificationCompleted(PhoneAuthCredential phoneAuthCredential)
This callback will be invoked in two situations:
1 — Instant verification. In some cases, the phone number can be instant without needing to send or enter a verification code.
2 — Auto-retrieval. Some devices using Google Play services can automatically detect the incoming verification SMS and perform verification without user action.
- onVerificationFailed(FirebaseException e)
This callback is invoked in an invalid request for verification is made, for instance, if the phone number format is not valid.
- onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token)
The SMS verification code has been sent to the provided phone number, we now need to ask the user to enter the code and then construct a credential by combining the code with a verification ID.
3) PhoneAuthCredential object
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, mCode);
After the user enters the verification code received from Firebase to user’s phone, a PhoneAuthCredential object is created by using verification code and verification ID that passed to the onCodeSent() callback method.
Sign In user
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
FirebaseUser currentUser = mAuth.getCurrentUser();
String userId = currentUser.getUid();
// Sign in success, update the UI
} else {
// Sign in failed, display a message and update the UI
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
}
}
}
});
}
After you get a PhoneAuthCredential object, complete the sign in by passing an object to FirebaseAuth.signInWithCredential.
LoginActivity.java detail code
public class LoginActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private Spinner mCountrySpinner;
private EditText mMobileNumberText;
private EditText mVerificationCodeText;
private Button mGetCodeButton;
private Button mSignInButton;
private ProgressDialog mProgressDialog;
private TextView mMessageTextView;
private DatabaseReference mDatabase;
private String mVerificationId;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private FirebaseAuth mAuth;
private String mCountryCode;
private String mMobileNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mCountrySpinner = findViewById(R.id.mobile_country);
mMobileNumberText = findViewById(R.id.mobile_number);
mVerificationCodeText = findViewById(R.id.mobile_code);
mGetCodeButton = findViewById(R.id.mobile_code_button);
mSignInButton = findViewById(R.id.mobile_login_button);
mMessageTextView = findViewById(R.id.mobile_otp_message);
mProgressDialog = new ProgressDialog(this);
mAuth = FirebaseAuth.getInstance();
mCountrySpinner.setOnItemSelectedListener(this);
mGetCodeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String mobile_number = mMobileNumberText.getText().toString();
checkMobileNumber(mobile_number);
}
});
mSignInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String mCode = mVerificationCodeText.getText().toString();
PhoneAuthCredential mAuthCredential = PhoneAuthProvider.getCredential(mVerificationId, mCode);
signInWithPhoneAuthCredential(mAuthCredential);
}
});
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
}
@Override
public void onVerificationFailed(FirebaseException e) {
}
@Override
public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) {
mVerificationId = verificationId;
mResendToken = token;
mMobileNumberText.setEnabled(false);
mVerificationCodeText.setVisibility(View.VISIBLE);
mMessageTextView.setVisibility(View.VISIBLE);
mGetCodeButton.setVisibility(View.GONE);
mSignInButton.setVisibility(View.VISIBLE);
mProgressDialog.dismiss();
}
};
}
private void checkMobileNumber(String mobile_number) {
if(mCountryCode.isEmpty()) {
Toast.makeText(LoginActivity.this, “Please select Country code”, Toast.LENGTH_SHORT).show();
} else if(mobile_number.isEmpty() || mobile_number.length() < 10) {
mMobileNumberText.setError(“Mobile number is required of 10 digits.”);
} else {
mMobileNumber = mCountryCode+””+mobile_number;
sendVerificationNumber(mMobileNumber);
}
}
private void sendVerificationNumber(String mMobileNumber) {
mProgressDialog.setMessage(“Please wait a moment”);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
PhoneAuthProvider.getInstance().verifyPhoneNumber(mMobileNumber, 60, TimeUnit.SECONDS, this, mCallbacks);
}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mProgressDialog.setMessage(“Please wait a moment”);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
FirebaseUser currentUser = mAuth.getCurrentUser();
assert currentUser != null;
final String userId = currentUser.getUid();
mDatabase = FirebaseDatabase.getInstance().getReference().child(“user_info”).child(userId);
Map<String, Object> userMap = new HashMap<>();
userMap.put(“user_mobile”, mMobileNumber);
userMap.put(“timestamp”, ServerValue.TIMESTAMP);
mDatabase.updateChildren(userMap, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if(databaseError == null) {
mProgressDialog.dismiss();
Intent businessIntent = new Intent(LoginActivity.this, MainActivity.class);
businessIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(businessIntent);
finish();
mProgressDialog.dismiss();
} else {
mProgressDialog.dismiss();
Toast.makeText(LoginActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
} else {
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
}
mProgressDialog.dismiss();
}
}
});
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
mCountryCode = String.valueOf(mCountrySpinner.getSelectedItem());
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
MainActivity.java

public class MainActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private FirebaseUser mUser;
private DatabaseReference mUserDatabase;
private DatabaseReference mRootDatabase;
private String mCurrentUserId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
if(mAuth != null) {
mUser = mAuth.getCurrentUser();
if (mUser != null) {
mCurrentUserId = mUser.getUid();
mRootDatabase = FirebaseDatabase.getInstance().getReference();
mUserDatabase = mRootDatabase.child(“user_info”).child(mCurrentUserId);
} else {
sendToStart();
}
}
}
@Override
public void onStart() {
super.onStart();
FirebaseUser currentUser = mAuth.getCurrentUser();
if(currentUser == null) {
sendToStart();
}
}
private void sendToStart() {
Intent startIntent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(startIntent);
finish();
}
}