Photo by Pixabay

Implementasi SMS Retriever API di Android

One Time Password (OTP) via SMS dapat mempermudah pengguna aplikasi dalam proses autentikasi. Secara garis besar, proses nya dapat dilihat dalam gambar berikut:

Proses autentikasi via SMS. (https://codeforgeek.com/2017/01/mobile-number-verification-using-laravel/)

Dengan metode OTP via SMS, user cukup memasukkan nomor handphone, kemudian kode OTP akan dikirimkan ke user via SMS. Kode ini harus memiliki waktu expire (biasanya dalam hitungan menit atau jam) dan hanya bisa digunakan satu kali pakai saja. Untuk lebih detailnya dapat di lihat di white paper berikut OTP-Based Two-Factor Authentication Using Mobile Phones.

Pada tulisan ini saya akan membahas cara implementasi SMS Retriver API pada Android. Dengan menggunakan API ini, user tidak perlu dimintai permission READ_SMS dan RECEIVE_SMS.

Permintaan permission untuk membaca SMS

Untuk bisa menggunakan API ini, kita user harus memiliki Play services versi 10.2 atau lebih baru. Dan di app nya sendiri perlu menambahkan package berikut:

// google play services
implementation "com.google.android.gms:play-services-gcm:16.0.0"
implementation "com.google.android.gms:play-services-auth:16.0.1"

Kemudian buat jalankan SMS retriever client:

val smsRetrieverClient = context
?.let { SmsRetriever.getClient(it) }
?: return

val smsRetrieverTask = smsRetrieverClient.startSmsRetriever()

Timber.d("SMS retriever has been started")

smsRetrieverTask.addOnSuccessListener {
Timber.d("smsRetrieverTask has been succeed")
}

smsRetrieverTask.addOnCanceledListener {
Timber.d("smsRetrieverTask has been cancelled")
}

Lalu tambahkan Broadcast Receiver untuk menerima SMS dengan OTP:

class SmsOtpReceiver : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == SmsRetriever.SMS_RETRIEVED_ACTION) {
val extras = intent.extras ?: return
val status = extras.get(SmsRetriever.EXTRA_STATUS) as Status

when (status.statusCode) {
CommonStatusCodes.SUCCESS -> {
val message = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String

Timber.d("isi SMS dengan OTP: $message")
// Proses SMS disini

}

CommonStatusCodes.TIMEOUT -> {
Timber.e("Timeout, no message")
}
}
}
}
}

Dan jangan lupa untuk menambahkan Broadcast Receiver nya ke manifest:

<receiver android:name=".feature.auth.presentation.smsotp.SmsOtpReceiver" android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>

Di sisi server kita juga harus menambah kan hash signature dari applikasi Android ke dalam pesan SMS nya serta mengubah format SMS seperti berikut:

<#> + Pesan SMS + app hash signature

Contoh:
<#> Kode OTP Anda adalah: AVB123
FA+9qCX9VSu

Untuk mendapatkan hash signature dari aplikasi Android, dapat menggunakan kode pada repo ini. Dan untuk versi Kotlin nya dapat di lihat disini.
Dengan kode di atas, kita bisa langsung dapat membaca SMS OTP tanpa perlu meminta access permission ke user. Untuk lebih detailnya dapat dilihat di dokumentasi Google Developer.

A lifelong learner