How to Implement OTP-Mobile Verification using Firebase Authentication
Introduction
Most of the modern apps nowadays use SMS mobile login via sending verification code to the preregistered mobile number. In this tutorial, we are going to implement firebase authentication via SMS code to user’s mobile.
Prerequisites
- you suppose to have the latest version of Android Studio.
- Android smartphone for testing, as OTP cannot be sent to an emulator.
- firebase Account to create a new project and enable mobile login via OTP.
App Overview
Create a new project for implementing the OTP-Authentication feature provided by Firebase. The app will have a simple activity with multiple buttons and EditTexts for typing mobile number, OTP and Request OTP, verify OTP and Logout the session. Simply the user will enter his mobile number then press request OTP. a timer will countdown waiting for OTP-token to be sent as SMS to that number. once the user got the OTP, he can type and Press verify. If the OTP does not match then it will pop a toast message, “Incorrect OTP”. Users can logout after successful verification.
Here is what the app finish will look like:
Setting Up Project
Step #1: Create A New Android Studio Project
- Start Android Studio and Click on “new project”.
- Give your application a name, mine is “firebaseCodeLab”.
- Click next and choose the Target android device.
- next, choose an empty activity to keep things simple.
- next, name your Activity and click finish to build the project.
Step #2: Add Firebase To your project
- Go to Firebase Console
- Sign in with your Gmail
- On the welcome screen of Firebase click on Add project
- Then register your app as below
- you can get the SHA-1 from:
- the SHA-1 will appear as below
- then press register app and follow the steps.
After that, add the dependencies to your project as described below
Don’t forget to give internet permission before testing :’)
Now go back to Firebase console and click on Project Overview. In Discover Firebase section there is a card named Authentication, click on GET STARTED on Authentication card.
Press on the Phone section and the following image will appear.
by enabling the toggle button, you have successfully added the OTP-Authentication feature to your project and its ready for usage.
NOTE: you can add phone numbers with fixed OTP-token for testing purposes. it's optional and recommended to set it up to avoid blocking your device by google while testing.
Screen Design
the style will look like
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
and colors…
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:60"
app:layout_constraintBaseline_toBaselineOf="@+id/button"
app:layout_constraintEnd_toStartOf="@+id/button"
app:layout_constraintHorizontal_bias="0.95"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:text="Current User:"
app:layout_constraintBottom_toTopOf="@+id/textInputLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textView4"
app:layout_constraintHorizontal_bias="0.19"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.37" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="----"
app:layout_constraintBaseline_toBaselineOf="@+id/textView3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/textView3"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="mobile no"
app:errorEnabled="true"
app:helperText="type your number"
app:helperTextEnabled="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2">
<com.google.android.material.textview.MaterialAutoCompleteTextView
android:id="@+id/outlined_exposed_dropdown_editable"
android:layout_width="match_parent"
android:inputType="phone"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Verify OTP"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/logout"
app:layout_constraintHorizontal_bias="0.50"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputET"
app:layout_constraintVertical_bias="0.0" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputET"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint=" Enter OTP"
app:helperText=" Enter OTP"
app:helperTextEnabled="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/button"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintVertical_bias="0.3">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberPassword"
android:maxLength="6"
android:layout_margin="5dp" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Request OTP"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@+id/textInputET"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.95"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed" />
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="logout"
android:textAllCaps="false"
app:layout_constraintBaseline_toBaselineOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/button2" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top" />
</androidx.constraintlayout.widget.ConstraintLayout>
the screen will be like
Kotin Code
Step #1: linking XML to Main Activity
lateinit var currentUserPhone: TextView
lateinit var otpTV: TextView
lateinit var otpET: TextInputEditText
lateinit var sendOTPbtn: Button
lateinit var verifyOTPbtn: Button
lateinit var logout: Button
lateinit var autoCompleteET: MaterialAutoCompleteTextViewprivate fun defineUI() {
sendOTPbtn = findViewById(R.id.button)
verifyOTPbtn = findViewById(R.id.button2)
otpTV = findViewById(R.id.textView)
otpET = findViewById(R.id.editText)
currentUserPhone = findViewById(R.id.textView4)
logout = findViewById(R.id.logout)
autoCompleteET = findViewById(R.id.outlined_exposed_dropdown_editable)
}
Step #2: define Firebase Auth and adding callbacks
lateinit var auth: FirebaseAuth
val TIME_OUT = 60
var mCallback: OnVerificationStateChangedCallbacks? = null//.... some code in between ....//
auth = FirebaseAuth.getInstance()
mCallback = object : OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
Toast.makeText(this@MainActivity, "verification completed", Toast.LENGTH_SHORT)
.show()
}
override fun onVerificationFailed(e: FirebaseException) {
Toast.makeText(this@MainActivity, "verification failed", Toast.LENGTH_SHORT).show()
Log.d("FirebaseException", e.toString())
}
override fun onCodeSent(
s: String,
forceResendingToken: ForceResendingToken
) {
super.onCodeSent(s, forceResendingToken)
verificationCode = s
Log.d("verificationCode", verificationCode)
Toast.makeText(this@MainActivity, "Code Sent", Toast.LENGTH_SHORT).show()
job = if (job == null || job!!.isCancelled)
countDown()
else {
job!!.cancel()
countDown()
}
}
}
Step #3: Implement onCLickListeners to Generate OTP button to send SMS
sendOTPbtn.setOnClickListener {
//TODO send OTP to the selected phone number
if (autoCompleteET.text != null && autoCompleteET.text.isNotEmpty())
PhoneAuthProvider.getInstance().verifyPhoneNumber(
autoCompleteET.text.toString(),// Phone number to verify
TIME_OUT.toLong(), // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this@MainActivity, // Activity (for callback binding)
mCallback!!
)
else {
hideKeyboard()
Toast
.makeText(
this@MainActivity,
"Please type phone number or pick from list",
Toast.LENGTH_SHORT
)
.show()
}
}
Moreover, for verifying OTP, we add
verifyOTPbtn.setOnClickListener {
hideKeyboard()
if (otpET.text!!.isNotEmpty()) {
val credential =
PhoneAuthProvider.getCredential(verificationCode, otpET.text.toString())
SigninWithPhone(credential)
} else {
Toast
.makeText(
this@MainActivity,
"Please type OTP number",
Toast.LENGTH_SHORT
)
.show()
}
}private fun SigninWithPhone(credential: PhoneAuthCredential) {
auth.signInWithCredential(credential)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Toast.makeText(this@MainActivity, "Correct OTP", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(this@MainActivity, "Incorrect OTP", Toast.LENGTH_SHORT)
.show()
}
}
}
Finally, set click listener on logout to sign-out from the app.
logout.setOnClickListener {
FirebaseAuth.getInstance().signOut()
}
Conclusion
In this tutorial, you learned about the firebase authentication to verify the user of your app via SMS OTP and get the user’s phone number from firebase user data. you can find the source code here from gitHub.
If you liked this post, give it a lot of claps. I’d be very grateful if you’d help it spread, sharing it on Twitter, Facebook or LinkedIn. Thank you!