diff --git a/android/build.gradle b/android/build.gradle index 64be700..a51fe51 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -46,12 +46,13 @@ android { } defaultConfig { - minSdkVersion 19 + minSdkVersion 21 } dependencies { - implementation 'com.google.android.gms:play-services-auth:20.3.0' - implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0' + implementation "com.google.android.gms:play-services-auth:21.3.0" + implementation "com.google.android.gms:play-services-auth-api-phone:18.1.0" + implementation "androidx.activity:activity:1.5.1" implementation "androidx.fragment:fragment:1.5.4" } diff --git a/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsRetrieverReceiver.kt b/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsRetrieverReceiver.kt index 4952430..70a0715 100644 --- a/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsRetrieverReceiver.kt +++ b/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsRetrieverReceiver.kt @@ -6,31 +6,30 @@ import android.content.Intent import com.google.android.gms.auth.api.phone.SmsRetriever import com.google.android.gms.common.api.CommonStatusCodes import com.google.android.gms.common.api.Status - class SmsRetrieverReceiver : BroadcastReceiver() { lateinit var smsBroadcastReceiverListener: SmsRetrieverBroadcastReceiverListener override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action != SmsRetriever.SMS_RETRIEVED_ACTION) return - if (intent?.action == SmsRetriever.SMS_RETRIEVED_ACTION) { + val extras = intent.extras ?: return - val extras = intent.extras - val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status + val status = extras.get(SmsRetriever.EXTRA_STATUS) as? Status ?: return - when (smsRetrieverStatus.statusCode) { - CommonStatusCodes.SUCCESS -> { - extras.get(SmsRetriever.EXTRA_SMS_MESSAGE)?.also { - smsBroadcastReceiverListener.onSuccess(it as String) - } + when (status.statusCode) { + CommonStatusCodes.SUCCESS -> { + // Safely cast the SMS message to String. + val smsMessage = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as? String + if (smsMessage != null) { + smsBroadcastReceiverListener.onSuccess(smsMessage) } - - CommonStatusCodes.TIMEOUT -> { - try { - smsBroadcastReceiverListener.onFailure() - } catch (e: Exception) { - ///DO NOTHING, end listening - } + } + CommonStatusCodes.TIMEOUT -> { + try { + smsBroadcastReceiverListener.onFailure() + } catch (e: Exception) { + // Do nothing; end listening. } } } @@ -40,4 +39,4 @@ class SmsRetrieverReceiver : BroadcastReceiver() { fun onSuccess(sms: String?) fun onFailure() } -} \ No newline at end of file +} diff --git a/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsUserConsentReceiver.kt b/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsUserConsentReceiver.kt index 605ea5e..200cf46 100644 --- a/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsUserConsentReceiver.kt +++ b/android/src/main/kotlin/ru/surfstudio/otp_autofill/SmsUserConsentReceiver.kt @@ -6,30 +6,39 @@ import android.content.Intent import com.google.android.gms.auth.api.phone.SmsRetriever import com.google.android.gms.common.api.CommonStatusCodes import com.google.android.gms.common.api.Status - class SmsUserConsentReceiver : BroadcastReceiver() { lateinit var smsBroadcastReceiverListener: SmsUserConsentBroadcastReceiverListener 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 ?: return - val extras = intent.extras - val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status - - when (smsRetrieverStatus.statusCode) { + when (status.statusCode) { CommonStatusCodes.SUCCESS -> { - extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT)?.also { - smsBroadcastReceiverListener.onSuccess(it) + extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT)?.let { consentIntent -> + // Validate that the intent resolves to Google Play Services + val pm = context?.packageManager + if (pm != null) { + val resolvedActivity = consentIntent.resolveActivity(pm) + if (resolvedActivity != null && + resolvedActivity.packageName == "com.google.android.gms") { + // Create a safe copy: clear any component or selector that might be maliciously set + val safeIntent = Intent(consentIntent).apply { + component = null + selector = null + } + smsBroadcastReceiverListener.onSuccess(safeIntent) + } + } } } - CommonStatusCodes.TIMEOUT -> { - try{ + try { smsBroadcastReceiverListener.onFailure() } catch (e: Exception) { - ///DO NOTHING, end listening + // Do nothing; end listening. } } } @@ -40,4 +49,4 @@ class SmsUserConsentReceiver : BroadcastReceiver() { fun onSuccess(intent: Intent?) fun onFailure() } -} \ No newline at end of file +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 014e015..6fca3d0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -47,9 +47,11 @@ class _MyAppState extends State { onCodeReceive: (code) => print('Your Application receive code - $code'), otpInteractor: _otpInteractor, )..startListenUserConsent( - (code) { + (sms) { + debugPrint('Your Application captured sms - $sms'); final exp = RegExp(r'(\d{5})'); - return exp.stringMatch(code ?? '') ?? ''; + final extractedCode = exp.stringMatch(sms ?? '') ?? ''; + return extractedCode; }, strategies: [ SampleStrategy(),