aws-amplify / aws-sdk-android

AWS SDK for Android. For more information, see our web site:
https://docs.amplify.aws
Other
1.02k stars 548 forks source link

Session issue : No cached session #3572

Open lolucosmin opened 1 month ago

lolucosmin commented 1 month ago

Describe the bug Hello, in our project we are using AWS Mobile client version 2.75.0 and lately we have a weird issue on Huawei devices. We have a weird session error: No cached session, the the strange thing is the user has a valid state: User State: SIGNED_IN User Session: will expire at 5/11/24 5:25 PM If I interogate the SDK about user state and sign in state all looks ok, but in logs I see a lot of warnings, I will post here all the details.

@tylerjroach can you help us with this weird error, for us is a major issue.

Environment Information (please complete the following information):

Additional context ----------Log 1---------- Error in decrypting data. javax.crypto.AEADBadTagException at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517) at javax.crypto.Cipher.doFinal(Cipher.java:2055) at com.amazonaws.internal.keyvaluestore.AWSKeyValueStore.decrypt(AWSKeyValueStore.java:435) at com.amazonaws.internal.keyvaluestore.AWSKeyValueStore.get(AWSKeyValueStore.java:252) at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.readCachedTokens(CognitoUser.java:2762) at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.getCachedSession(CognitoUser.java:1293) at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.getSession(CognitoUser.java:1023) at com.amazonaws.mobile.client.AWSMobileClient$12.run(AWSMobileClient.java:2030) at com.amazonaws.mobile.client.internal.InternalCallback.await(InternalCallback.java:115) at com.amazonaws.mobile.client.AWSMobileClient.getTokens(AWSMobileClient.java:1996) at com.amazonaws.mobile.client.AWSMobileClient.getUserStateDetails(AWSMobileClient.java:1120) at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:900) at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:897) at com.amazonaws.mobile.client.internal.ReturningRunnable.await(ReturningRunnable.java:31) at com.amazonaws.mobile.client.AWSMobileClient.currentUserState(AWSMobileClient.java:879) at com.bfan.sso.logic.services.aws.auth.AmazonAuthService.isSessionExpired(AmazonAuthService.java:132) at com.bfan.sso.logic.server.BaseObsParams.lambda$getSessionStateObserver$1(BaseObsParams.java:52) at com.bfan.sso.logic.server.BaseObsParams$$ExternalSyntheticLambda0.subscribe(D8$$SyntheticClass:0) at io.reactivex.rxjava3.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:41) at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173) at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:52) at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173) at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:644) at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65) at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:929) Caused by: android.security.KeyStoreException: Signature/MAC verification failed at android.security.KeyStore.getKeyStoreException(KeyStore.java:1593) at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224) at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:386) at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506) at javax.crypto.Cipher.doFinal(Cipher.java:2055)  at com.amazonaws.internal.keyvaluestore.AWSKeyValueStore.decrypt(AWSKeyValueStore.java:435)  at com.amazonaws.internal.keyvaluestore.AWSKeyValueStore.get(AWSKeyValueStore.java:252)  at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.readCachedTokens(CognitoUser.java:2762)  at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.getCachedSession(CognitoUser.java:1293)  at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.getSession(CognitoUser.java:1023)  at com.amazonaws.mobile.client.AWSMobileClient$12.run(AWSMobileClient.java:2030)  at com.amazonaws.mobile.client.internal.InternalCallback.await(InternalCallback.java:115)  at com.amazonaws.mobile.client.AWSMobileClient.getTokens(AWSMobileClient.java:1996)  at com.amazonaws.mobile.client.AWSMobileClient.getUserStateDetails(AWSMobileClient.java:1120)  at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:900)  at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:897)  at com.amazonaws.mobile.client.internal.ReturningRunnable.await(ReturningRunnable.java:31)  at com.amazonaws.mobile.client.AWSMobileClient.currentUserState(AWSMobileClient.java:879)  at com.bfan.sso.logic.services.aws.auth.AmazonAuthService.isSessionExpired(AmazonAuthService.java:132)  at com.bfan.sso.logic.server.BaseObsParams.lambda$getSessionStateObserver$1(BaseObsParams.java:52)  at com.bfan.sso.logic.server.BaseObsParams$$ExternalSyntheticLambda0.subscribe(D8$$SyntheticClass:0)  at io.reactivex.rxjava3.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:41)  at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173)  at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:52)  at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173)  at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)  at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:644)  at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)  at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)  at java.util.concurrent.FutureTask.run(FutureTask.java:266)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)  at java.lang.Thread.run(Thread.java:929) 

----------Log 2----------

Tokens are invalid, please sign-in again. java.lang.Exception: No cached session. at com.amazonaws.mobile.client.AWSMobileClient$12$1.signalTokensNotAvailable(AWSMobileClient.java:2079) at com.amazonaws.mobile.client.AWSMobileClient$12$1.getAuthenticationDetails(AWSMobileClient.java:2049) at com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser.getSession(CognitoUser.java:1036) at com.amazonaws.mobile.client.AWSMobileClient$12.run(AWSMobileClient.java:2030) at com.amazonaws.mobile.client.internal.InternalCallback.await(InternalCallback.java:115) at com.amazonaws.mobile.client.AWSMobileClient.getTokens(AWSMobileClient.java:1996) at com.amazonaws.mobile.client.AWSMobileClient.getUserStateDetails(AWSMobileClient.java:1120) at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:900) at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:897) at com.amazonaws.mobile.client.internal.ReturningRunnable.await(ReturningRunnable.java:31) at com.amazonaws.mobile.client.AWSMobileClient.currentUserState(AWSMobileClient.java:879) at com.bfan.sso.logic.services.aws.auth.AmazonAuthService.isSessionExpired(AmazonAuthService.java:132) at com.bfan.sso.logic.server.BaseObsParams.lambda$getSessionStateObserver$1(BaseObsParams.java:52) at com.bfan.sso.logic.server.BaseObsParams$$ExternalSyntheticLambda0.subscribe(D8$$SyntheticClass:0) at io.reactivex.rxjava3.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:41) at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173) at io.reactivex.rxjava3.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:52) at io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13173) at io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:644) at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65) at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:929)

lolucosmin commented 1 month ago

If I interogate the SDK like this after I get that error and warnings I have this results:

AWSMobileClient.getInstance().getUsername() - same like before getting the error AWSMobileClient.getInstance().isSignedIn() - true AWSMobileClient.getInstance().getIdentityId() - another identity

lolucosmin commented 1 month ago

I have more information about this issue: -appear after 1H when the aws should refresh the session. -in UserStateDetails there is a exception but that method is protected and you can not interogate the skd to see if is null or not.

Screenshot 2024-05-13 160750

As you can see in image the state for user is SIGNED_IN but there no good session also if I as for AWSMobileClient.getInstance().getIdentityId() now I have a new one instead the real one. What I see here the SDK is not changing the user state into GUEST or SIGNED_OUT.

I tried also to intercept that exception but is not working:

public boolean isSessionExpired() { UserStateDetails userState; try { userState = AWSMobileClient.getInstance().currentUserState(); } catch (Exception ex) { return true; } ........

Is weird because in SDK there is a catch @WorkerThread public UserStateDetails currentUserState() { try { return _currentUserState().await(); } catch (Exception e) { throw new RuntimeException("Failed to retrieve user state.", e); } } but is not going into catch block.

So I have no idea how to manage this situation @tylerjroach, do you have a suggestion for me?

yuhengshs commented 1 month ago

Hi @lolucosmin ,

Thanks for reaching out, we will take a look into the issue and provide updates here.

tylerjroach commented 1 month ago

@lolucosmin Huewei devices may be tricky.Are these older devices with Google Play Services, or the newer Huewei devices withouth Google support.

I'm afraid these devices look like they do not appear to have proper Android KeyStore implementations.


Error in decrypting data. javax.crypto.AEADBadTagException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)```

This crash is coming directly from OS KeyStore implementation.
lolucosmin commented 1 month ago

@lolucosmin Huewei devices may be tricky.Are these older devices with Google Play Services, or the newer Huewei devices withouth Google support.

I'm afraid these devices look like they do not appear to have proper Android KeyStore implementations.

Error in decrypting data. javax.crypto.AEADBadTagException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)```

This crash is coming directly from OS KeyStore implementation.

Indeed, there are 2 types with Google Services and without, I tested on devices(4 devices) without Google Services and on all of them I have same issue, the sign in is successful but after 1h no session refresh.

But I have a question related to AWSMobileClient SDK. Why there int this function is a catch if you want to throw that exception? Also why that exception from my image above is not in state of user? At least if it will be in state of user we can check that variable. @WorkerThread public UserStateDetails currentUserState() { try { return _currentUserState().await(); } catch (Exception e) { throw new RuntimeException("Failed to retrieve user state.", e); } }

lolucosmin commented 1 week ago

@tylerjroach any news related to this issue?

tylerjroach commented 1 week ago

@lolucosmin Are you only seeing this on Huewei devices? And if so, is it all Huewei devices you have tested. We have a Huewei device we can attempt to test with to see if we can replicate the issue.

lolucosmin commented 1 week ago

@lolucosmin Are you only seeing this on Huewei devices? And if so, is it all Huewei devices you have tested. We have a Huewei device we can attempt to test with to see if we can replicate the issue.

Hi @tylerjroach , so our app is using aws login system and we have a lot of users for our app which has Huawei devices, almost every day we are getting complains about this issue. This issue appear on both types of devices: devices without google services which is very easy to reproduce it, because appear every 1H. For the other types looks like this issue is randomly. But main purpose is to find a fix for that devices which has no google services to make a better experience for our users.

Thx.