No more SMS permission required for SMS verification in Android O+(8+)

iamVariable
4 min readMar 21, 2019

It’s been just about a year since Google released Android Nougat. In the next version of its Android operating system, it revealed the first developer preview of Android O (Hoping it’ll named Android Oreo) on 21 March 2017.

As we all know security is the biggest challenge while developing any product. Same thing is also applied with Android devices as user’s sensitive data is stored on it. To improve the security Android 6.0 or more commonly known as Android M, came with the great feature called runtime request permissions.

Using runtime request permission user of the device can control the permissions of the different application installed on their Android devices. And users grant permissions to apps while the app is running, not when they install the app.

If our application required to read the SMS, then user has to grant to android.permission.READ_SMS permission to our application and users generally avoid to grant read SMS permission because of its sensitivity.

Your’e in safe zone now

What is SMS Verification?

SMS verification is also known to authenticate whether the user is genuine or fake one, backend server sends a text message containing the some digit SECURITY_CODE to their Mobile Number or Email. Then client take the input code and send it to the server. If server verification successful then it sends successful response back to the client and user authentication is a successfully completed.

In Android most of the time when user sign up into our application, we verify the details via their mobile number in order to get genuine users. A very typical example is Whatsapp. In iOS12 also introduced their part using Siri.

Drawbacks of reading SMS

There are several of disadvantages of reading the SMS from the user’s device as follows-

- Additional request permission READ_SMS (from Android M(6.0)& above)

- Apps have to search the appropriate SMS

- With the full control to read SMS, apps can track user’s sensitive messages

- Other applications can also read the SMS information of our application.

Improvements in Android O

Most of you aware of Android O is coming up with variety of system and API behavior changes and Google is continuously working to improve the security and performance of the Android system. So Android O also brings SMS verification in a different way.

Google introduced a new API called createAppSpecificSmsToken() in the SmsManager class. This will solve the above mentioned problem.

Following are the steps involved to use this new API-

1. Generate a token at backend server and send it to client (Android)

2. Call createAppSpecificSmsToken() API with received token

3. Once message is received, we’ll get a callback to our PendingIntent without any permissions.

This means no manual code or token value is required enter. Even no process is needed to read the SMS to auto detect the code at all. With this new API we can directly get callbacks to our application.

OTP verification with SMS retriever API

Prerequisites

  1. Android smartphone with the phone number & running Google play services 10.2.X or higher.
  2. A server which can send OTP in the predefined format.

Android Implementation

  1. Add play-services-auth as dependency in your build.gradle file.
implementation "com.google.android.gms:play-services-auth:16.0.1"

2. Get the phone number from user to send it to the server. Alternatively, you can implement the hint picker to prompt the user to choose from the phone numbers stored on the device and thereby avoid having to manually type a phone number.

3. Initialize SmsRetrieverClient and listen to the Success/Failure callback like below.

val client: SmsRetrieverClient = SmsRetriever.getClient(this) val task = client.startSmsRetriever() task.addOnSuccessListener { // Successfully started retriever, expect broadcast intent} task.addOnFailureListener { // Failed to start retriever, inspect Exception for more details}

Note: Once the SmsRetrieverClientstarts, it waits for ONE matching SMS until the timeout of 5 minutes.

4. As soon as addOnSuccessListener is triggered, you can send the phone number to the server (through REST API) to get the OTP message back to the device from server.

5. Now that the server sends the verification SMS to our mobile, we need BroadcastReceiver to listen & read the message content like below.

6. Add the receiver in AndroidManifest.xml .

Server-side implementation

To get the SmsRetrieverClient to work, a specific format to be followed at server side while creating the OTP message.

  1. The message should start with the prefix <#>
  2. The message must be no longer than 140 bytes
  3. The message should end with the 11-character hash string that identifies your app.

Google Play services use the hash string to determine which verification messages to send to your app. The hash key is made of the app’s package name and app’s public key certificate. You can refer official site for more info or use AppSignatureHelper to generate the hash string programatically. Generating hash string is a one time process.

4. Sample verification message received at the mobile side would look something like this.

<#> Your ExampleApp code is: 123ABC78
ERA+9rSf9VSu

Once you receive a message from the server, it will now be picked by our app. You can extract the OTP and use it for verification.

Update: These are quite a few alternatives which I could address for now. But this won’t cover everything. For eg, CALL_LOG, I didn’t find any alternative solution so far. If anybody found out anything, please do share.

--

--

iamVariable

Experienced Mobile Application developer and in full software development lifecycle, including analysis, design, development, deployment.