Easy SMS Verification in Android: SMS User Consent API

Nowadays, SMS verification is the best way that is being used by mobile applications for login purpose. All you need to do is just enter your mobile number, get a One-Time Password and finally enter that OTP in your application and verify. But the problem that arises here is that to have the OTP for your application, you need to view all your messages and also at the same time you need to input the OTP by your own. No doubt, there are certain libraries on Github that will do the automatic code completion for you but here we are having the SMS User Consent API, that will make our task very easy.

In this blog, we will learn our SMS User Consent API and see how this can be easily used for SMS verification. So, let’s get started.

What is SMS User Consent API?

SMS User Consent API is used to retrieve the SMS by showing a prompt to the user to grant access to the content of a single SMS message. When the permission is granted by the user then the application will read the entire message and automatically fill the OTP or SMS verification code in the desired place. Following is the flow of SMS User Consent API:

Source: Google Developer Website

Here, if the user presses the Allow button, then the SMS verification code will be automatically filled up.

The flow of SMS User Consent API

The whole working of the SMS User Consent API can be divided into 3 steps:

  1. Start: To use SMS User Consent API, you have to start is first. But there is one condition with it, you have to start the API before sending the message or OTP to the server.
  2. Prompt: So, when you start the API, the Google Play Services will read the message and then allows your application to show a prompt to your users to grant permission to read the message containing the OTP or verification code. The user can either allow or decline the request to read the message.
  3. Read Message: Finally, if your application is having the permission to read the messages then with the help of API, your application will automatically enter the One Time Code for you.

Message Criteria

Certain criteria should be followed before using the SMS User Consent API:

  1. Contains One Time Code: You message must contain some One Time Code type of thing.
  2. Code format: The One Time Code should be 4–10 digit alphanumeric and 1 digit must be a number.
  3. Contacts: The message containing the One Time Code should not be received from any of your contacts.
  4. Timing: The API will look for the One Time Code for a maximum time of 5 minutes.

Using SMS User Consent API in Android

To use SMS User Consent API, we will be following the above mentioned three steps but before that, we will implement the library in our app. So, in the app level build.gradle file, add the below lines:

implementation "com.google.android.gms:play-services-auth:17.0.0"
implementation "com.google.android.gms:play-services-auth-api-phone:17.1.0"

After implementing the library, the next thing that is to be done is to get the user’s phone number. If you are not having the user’s phone number, then you should get it before starting the SMS verification. So, to obtain the user’s phone number, you can use the below code:

private val CREDENTIAL_PICKER_REQUEST = 1  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private fun requestHint() {
    val hintRequest = HintRequest.Builder()
        .setPhoneNumberIdentifierSupported(true)
        .build()
    val credentialsClient = Credentials.getClient(this)
    val intent = credentialsClient.getHintPickerIntent(hintRequest)
    startIntentSenderForResult(
        intent.intentSender,
        CREDENTIAL_PICKER_REQUEST,
        null, 0, 0, 0
    )
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        CREDENTIAL_PICKER_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                val credential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                // credential.getId();  <-- will need to process phone number string
            }
        // ...
    }
}

Our next step is to listen to the incoming messages. So, by using the smartSmsUserConsent() method, you can start listening for the incomming messages. If you know the number of the sender who is sending the SMS verification then then you can pass that number in the method ortherwise you can pass NULL.

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
val task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */)

So, our first step is done i.e. we have started the SMS User Consent API and our next duty is to send the SMS verification code. Here, you can apply your verification code sender to send the One Time Code on the user’s mobile number. So, if your SMS will satisfy all the four Message criteria of the API then the prompt will be shown to the user. So, you need to handle these broadcasts with a broadcast receiver that responds to SMS_RECEIVED_ACTION intents.

private val SMS_CONSENT_REQUEST = 2  // Set to an unused request code
private val smsVerificationReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

            when (smsRetrieverStatus.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    // Get consent intent
                    val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
                    } catch (e: ActivityNotFoundException) {
                        // Handle the exception ...
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    // Time out occurred, handle the error.
                }
            }
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
    registerReceiver(smsVerificationReceiver, intentFilter)
}

Once the user has granted the permission to read the code from your message then you can put the extracted code at the desired place. You have to do all these things in your onActivityResult() method.

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        // ...
        SMS_CONSENT_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                // Get SMS message content
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                // Extract one-time code from the message and complete verification
                // `message` contains the entire text of the SMS message, so you will need
                // to parse the string.
                val oneTimeCode = parseOneTimeCode(message) // define this function

                // send one time code to the server
            } else {
                // Consent denied. User can type OTC manually.
            }
    }
}

For better user experience, you can also give the feature entering the SMS verification code manually also because if the code received is on some other device then the user can manually enter the code in your app.

Conclusion

In this blog, we learned how to use the SMS User Consent API in our Android application. So, basically, we are having three steps i.e. Start, Prompt and Read Message. Firstly, we start the API before sending the code, after that a prompt is shown to the user to grant permission for code reading from the message and finally, if the permission is granted then the API extracts the code from your message and you can use that code.

Hope you learned something new from this blog. To learn some more cool topics of Android, you can read the blogs from our website.

Keep Learning :)

Team MindOrks!