Firebase User Phone Authentication verification by otp in Android

Sharing is caring!

As in my last tutorial, we understand the basic firebase concept like What is Firebase and How to use the Firebase features in our application? So I am not going into detail here about the basic understanding about the Firebase. To Use any feature of firebase we need to follow few basic simple steps to register my application.

Here are steps:

  1. Please go to Firebase console to create the project. Here you can pass the project name and enter your country name etc.
  2. You have to choose which platform do you want to use. Here we are configuring for Android platform, so I am choosing an option for Android app.
  3. Now you need to enter your package name of your project. Ex: Here my package name is “com.sunil.firebase”. Other fields are optional for debug mode. But if you want to release your app that time you need to pass the SHA-1 key.
  4. Once you have done your step.4 You will get downloaded one google-services.json file. You have to copy this file and paste into the app folder.

Great done well so far. Now you need to add Firebase dependencies to your Gradle file. Here please always check the latest version of the minimum crash and best feature.

compile 'com.firebaseui:firebase-ui-auth:3.0.0'
compile 'com.google.firebase:firebase-auth:11.4.2'

In my last tutorial, we already practiced the register and login with user email and password. I would be recommended to check the basic concept of Firebase about login and register with email and password then this post will help you to understand the concept Firebase User Authentication in android.

Now in this tutorial, we will earn how to login with a phone number to sending the OTP over users phone? For phone authentication of Firebase User, you need to enable the Phone Authenticate sign-in method from the firebase console.

Generally, Firebase phone Authentication can possible in two ways.

  1. Firebase AuthUI method
  2. Custom UI Phone Authentication

Firebase AuthUI method

Let’s discuss the first one where we can use the Firebase AuthUI which is provided by Firebase to Authenticate the user’s phone by OTP. Here Firebase AuthUI is provide everything for you to write the minimum line of code to authenticate phone. You need to write the Firebase AuthUI method call to authenticate and all other things will take care by Firebase. So this concept is pretty simple and easy to integrate our applications.

 @OnClick(R.id.btnFirebaseUI)
    public void clickFirebaseUI(){
       startActivityForResult(AuthUI.getInstance().createSignInIntentBuilder().setAvailableProviders(
                Arrays.asList(new AuthUI.IdpConfig.Builder(AuthUI.PHONE_VERIFICATION_PROVIDER).build())).build(), 1000);
    }

This minimum line of code will allow opening the Firebase Auth UI to enter the phone of the user to authenticate. Here You need to provide the correct information like country code and Phone number to authenticate. Now Firebase will start doing the job for you.

Now the second thing we need to take care the Firebase Authenticated result in onStartActvityResult. So let’s write the code for tracking the Firebase result.

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1000) {

            IdpResponse response = IdpResponse.fromResultIntent(data);
            if (resultCode == RESULT_OK) {
                if (!FirebaseAuth.getInstance().getCurrentUser().getPhoneNumber().isEmpty()) {
                    startActivity(new Intent(PhoneActivity.this, HomeActivity.class).putExtra("phone", FirebaseAuth.getInstance().getCurrentUser().getPhoneNumber()));
                    finish();
                    return;

                } else {
                    if (response == null) {
                        Toast.makeText(this, "Sign In Failed", Toast.LENGTH_SHORT).show();
                        return;
                    }

                    if (response.getErrorCode() == ErrorCodes.NO_NETWORK) {
                        Toast.makeText(this, "No Network", Toast.LENGTH_SHORT).show();

                        return;
                    }

                    if (response.getErrorCode() == ErrorCodes.UNKNOWN_ERROR) {
                        Toast.makeText(this, "unkown Error", Toast.LENGTH_SHORT).show();

                        return;
                    }
                }
            }
        }
    }

Here User will be logged in state to access all the feature of your app. If a user has done the task and wants to sign out then AuthUI provides API call to sign out.

@OnClick(R.id.btnSignout)
    public void clickSignout(){
        AuthUI.getInstance().signOut(HomeActivity.this).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                startActivity(new Intent(HomeActivity.this, PhoneActivity.class));
            }
        });
    }

Now We have done so for of the first method phone authentication.

Custom UI Phone Authentication

Let’s check how can we make this feature as custom, I mean, I don’t want the existing Firebase AuthUI feature. Basically, We want to use our app design for the same procedure. We can complete this task in basic three steps.

  1. Enter Phone to get OTP (Firebase provides verification id and token)
  2. Resend the opt or verification code if the otp did not get the provided on phone number.
  3. Enter the verification-id (otp code) and verify by Firebase API call

Let’s check how to proceed with the first step.

 @OnClick(R.id.button_start_verification)
    public void clickStartVerification(){
        getOtp(fieldPhoneNumber.getText().toString());
    }
 private void getOtp(String phoneNumber) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }

 mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(PhoneAuthCredential credential) {
                Log.d("", "onVerificationCompleted:" + credential);
                signInWithPhoneAuthCredential(credential);
            }

            @Override
            public void onVerificationFailed(FirebaseException e) {
                Log.w("", "onVerificationFailed", e);
                if (e instanceof FirebaseAuthInvalidCredentialsException) {
                    fieldPhoneNumber.setError("Invalid phone number.");
                } else if (e instanceof FirebaseTooManyRequestsException) {
                   // error log
                }
            }

            @Override
            public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) {
                Log.d("", "onCodeSent:" + verificationId);
                mVerificationId = verificationId;
                mResendToken = token;
            }
        };

Callback provides the three different methods to execute the task based on the firebase result. Here if the otp did not reach to provided phone number then you can call the resend the verification code again to your number. Let’s check the second steps.

  @OnClick(R.id.button_resend)
    public void clickResend(){
        resendVerificationCode(fieldPhoneNumber.getText().toString(), mResendToken);
    }
private void resendVerificationCode(String phoneNumber,
                                        PhoneAuthProvider.ForceResendingToken token) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks,         // OnVerificationStateChangedCallbacks
                token);             // ForceResendingToken from callbacks
    }

Firebase will send the result to the same callback method. Now suppose you got the verification code on your phone number and now you need to verify this code with firebase API. It means we reached the third step. Let’s check the third step for opt verification by using the Firebase API.

 @OnClick(R.id.button_verify_phone)
    public void clickVerifyPhone(){
        String code = fieldVerificationCode.getText().toString();
        if (TextUtils.isEmpty(code)) {
            fieldVerificationCode.setError("Cannot be empty.");
            return;
        }
        verifyPhoneNumberWithCode(mVerificationId, code);
    }
  private void verifyPhoneNumberWithCode(String verificationId, String code) {
        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
        signInWithPhoneAuthCredential(credential);
    }
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            Log.d(TAG, "signInWithCredential:success");
                            FirebaseUser user = task.getResult().getUser();
                            startActivity(new Intent(PhoneAuthActivity.this, HomeActivity.class).putExtra("phone", user.getPhoneNumber()));
                            finish();
                        } else {
                            Log.w(TAG, "signInWithCredential:failure", task.getException());
                            if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                fieldVerificationCode.setError("Invalid code.");
                            }
                        }
                    }
                });
    }

Here User can authenticate with success and failure based on the API response.  So we have done so for the custom UI for phone authentication for users. Here I divided code into three snippet part then it becomes difficult to understand for the beginner. Let’s share the whole Activity code together for easy life.

public class PhoneAuthActivity extends AppCompatActivity {

    @BindView(R.id.field_phone_number)
    EditText fieldPhoneNumber;
    @BindView(R.id.field_verification_code)
    EditText fieldVerificationCode;
    @BindView(R.id.button_start_verification)
    Button buttonStartVerification;
    @BindView(R.id.button_verify_phone)
    Button buttonVerifyPhone;
    @BindView(R.id.button_resend)
    Button buttonResend;

    private FirebaseAuth mAuth;
    private PhoneAuthProvider.ForceResendingToken mResendToken;
    private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
    String mVerificationId;
    private static final String TAG = "PhoneAuthActivity";


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_phone_auth);
        ButterKnife.bind(this);

        mAuth = FirebaseAuth.getInstance();
        mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(PhoneAuthCredential credential) {
                Log.d("", "onVerificationCompleted:" + credential);
                signInWithPhoneAuthCredential(credential);
            }

            @Override
            public void onVerificationFailed(FirebaseException e) {
                Log.w("", "onVerificationFailed", e);
                if (e instanceof FirebaseAuthInvalidCredentialsException) {
                    fieldPhoneNumber.setError("Invalid phone number.");
                } else if (e instanceof FirebaseTooManyRequestsException) {
                   
                }
            }

            @Override
            public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) {
                Log.d("", "onCodeSent:" + verificationId);
                mVerificationId = verificationId;
                mResendToken = token;
            }
        };

    }


    private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            Log.d(TAG, "signInWithCredential:success");
                            FirebaseUser user = task.getResult().getUser();
                            startActivity(new Intent(PhoneAuthActivity.this, HomeActivity.class).putExtra("phone", user.getPhoneNumber()));
                            finish();
                        } else {
                            Log.w(TAG, "signInWithCredential:failure", task.getException());
                            if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                fieldVerificationCode.setError("Invalid code.");
                            }
                        }
                    }
                });
    }

    private void getOtp(String phoneNumber) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks);        // OnVerificationStateChangedCallbacks
    }

    private void verifyPhoneNumberWithCode(String verificationId, String code) {
        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
        signInWithPhoneAuthCredential(credential);
    }

    private void resendVerificationCode(String phoneNumber,
                                        PhoneAuthProvider.ForceResendingToken token) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                phoneNumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                this,               // Activity (for callback binding)
                mCallbacks,         // OnVerificationStateChangedCallbacks
                token);             // ForceResendingToken from callbacks
    }

    @OnClick(R.id.button_start_verification)
    public void clickStartVerification(){
        getOtp(fieldPhoneNumber.getText().toString());
    }

    @OnClick(R.id.button_verify_phone)
    public void clickVerifyPhone(){
        String code = fieldVerificationCode.getText().toString();
        if (TextUtils.isEmpty(code)) {
            fieldVerificationCode.setError("Cannot be empty.");
            return;
        }
        verifyPhoneNumberWithCode(mVerificationId, code);
    }

    @OnClick(R.id.button_resend)
    public void clickResend(){
        resendVerificationCode(fieldPhoneNumber.getText().toString(), mResendToken);
    }

}

wrapping up: As we have seen that Firebase is awesome for instant building the app. Even if you do not have any backend ready till now then you can use the Firebase cloud for a backend to quick start your idea into the Android application. If you want to upload user profile while registering the user then Firebase provides the cloud storage to upload the file or image. Please check this post to upload a file on Firebase Storage in android.

Please do subscribe email to get all newsletters of this blog and if you feel that this post will help you to understand then do not forget to subscribe, share and comment below.

Happy Coding 🙂

4.7 3 votes
Article Rating

Similar Posts

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
test abc

I have implemented custom ui with firebase but not getting otp message

Devang Prajapati

Plz set a proper download link sir

Sonu

sir how to make a session management in firebase otp registration..???

Bineesh

Hi, how to manage scenario user retry his phone number for authenticaton. ?

arushi

hello,
can you help me that i want to create a project that contain both phone number and email.
-> phone no. and otp for verification and email for login