braintree / braintree_android

Braintree SDK for Android
https://developer.paypal.com/braintree/docs/start/hello-client/android/v4
MIT License
409 stars 234 forks source link

NullPointerException on KeystoreService.asBinder() while working with an InstantApp #561

Closed carlosjuarezflash closed 2 years ago

carlosjuarezflash commented 2 years ago

Issue description

I recently updated the version from 4.6.0 to 4.10.0 to remove jetifier of our application.

Our application uses Google Instant app and brain tree to tokenize a credit card to accept payments. everything was working correctly in 4.6, but with the updated version it no longer works.

this is the trace we see everytime we want to create a CardClient

Payment error: Attempt to invoke interface method 'android.os.IBinder android.system.keystore2.IKeystoreService.asBinder()' on a null object reference

e = {NullPointerException@34241} "java.lang.NullPointerException: Attempt to invoke interface method 'android.os.IBinder android.system.keystore2.IKeystoreService.asBinder()' on a null object reference" backtrace = 1 = {Class@34068} "class android.security.KeyStore2" 4 = {Class@34067} "class android.security.keystore2.AndroidKeyStoreSpi" 6 = {Class@16276} "class java.security.KeyStore" 7 = {Class@34065} "class androidx.security.crypto.MasterKeys" 9 = {Class@28890} "class androidx.security.crypto.MasterKey$Builder" 11 = {Class@27739} "class com.braintreepayments.api.BraintreeSharedPreferences" 13 = {Class@19730} "class com.braintreepayments.api.ConfigurationCache" 15 = {Class@24422} "class com.braintreepayments.api.ConfigurationLoader" 17 = {Class@19913} "class com.braintreepayments.api.BraintreeClient$1" 18 = {Class@21438} "class com.braintreepayments.api.AuthorizationLoader" 19 = {Class@22793} "class com.braintreepayments.api.BraintreeClient" 20 = {Class@22793} "class com.braintreepayments.api.BraintreeClient" 21 = {Class@20076} "class com.braintreepayments.api.CardClient"

some useful links

https://stackoverflow.com/questions/65398957/android-keystore-crashes-in-android-instant-app https://www.reddit.com/r/androiddev/comments/7a4tdw/why_no_hardware_backed_keystore_in_instant_apps/

is there any way to bypass the usage of keystore while creating the CardClient?

sshropshire commented 2 years ago

Hi @carlosjuarezflash thanks for using the Braintree SDK for Android. This is an interesting use case, we use encrypted shared prefs to store transient payment flow metadata.

We may want to no-op in this scenario when we are unable to obtain a reference to encrypted shared prefs. The only drawback would be a required network request to fetch the Braintree configuration after a cache miss.

If we choose to ignore the cache in this scenario, would that be a sufficient fix for your app?

carlosjuarezflash commented 2 years ago

Hi @sshropshire thanks for the quick response.

I suppose that would be an appropriate solution, unfortunately there's not much documentation about instant apps, so this cases are peculiar

let me know what can i do to help you.

sshropshire commented 2 years ago

@carlosjuarezflash definitely we appreciate the feedback. I created a PR to no-op in this scenario. This feels like the right call since the cache can be cleared at any time, and the SDK will fetch the configuration if needed. This should be fine since instant apps are more ephemeral than most use cases.

On the other hand, if having a working configuration cache would improve the experience of your instant app, feel free to file a separate ticket and we'll use the GitHub issue for tracking after we prioritize internally.

carlosjuarezflash commented 2 years ago

I appreciate all the work you did there.

thank you so much

sshropshire commented 2 years ago

@carlosjuarezflash for sure! Again thanks for the feedback. This is now live in version 4.12.0