Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session issue : No cached session #3572

Open
lolucosmin opened this issue May 11, 2024 · 14 comments
Open

Session issue : No cached session #3572

lolucosmin opened this issue May 11, 2024 · 14 comments
Labels
bug Something isn't working cognito Issues with the AWS Android SDK for Cognito

Comments

@lolucosmin
Copy link

lolucosmin commented May 11, 2024

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):

  • AWS Android SDK Version: [2.75.0]
  • Device: [all huawei devices]
  • Android Version: [7 and above]
  • Specific to simulators: [No]

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
Copy link
Author

lolucosmin commented May 11, 2024

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
Copy link
Author

lolucosmin commented May 13, 2024

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
Copy link
Contributor

Hi @lolucosmin ,

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

@yuhengshs yuhengshs added bug Something isn't working cognito Issues with the AWS Android SDK for Cognito labels May 13, 2024
@tylerjroach
Copy link
Member

@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
Copy link
Author

@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
Copy link
Author

@tylerjroach any news related to this issue?

@tylerjroach
Copy link
Member

@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
Copy link
Author

@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.

@lolucosmin
Copy link
Author

@tylerjroach any news about this issue? I see "No one assigned" and is a old one and is important.

@tylerjroach tylerjroach added the pending-maintainer-response Issue is pending response from an Amplify team member label Aug 13, 2024
@tylerjroach
Copy link
Member

We do not have a path forward for a fix at the moment.

AWS Android SDK and Amplify both use the Android KeyStore, although they each have different implementations. Amplify v2 uses EncryptedSharedPreferences library from Google.

These devices appear to have problematic implementations of the Android KeyStore. A functioning KeyStore is critical to securely encrypt data at rest on the device. We have no way to work around it.

@lolucosmin
Copy link
Author

lolucosmin commented Aug 16, 2024

We do not have a path forward for a fix at the moment.

AWS Android SDK and Amplify both use the Android KeyStore, although they each have different implementations. Amplify v2 uses EncryptedSharedPreferences library from Google.

These devices appear to have problematic implementations of the Android KeyStore. A functioning KeyStore is critical to securely encrypt data at rest on the device. We have no way to work around it.

Hi @tylerjroach , OK I see the problem, but at least we can do something to fix the status for user?
Ex 1: when we have this exception

Tokens are invalid, please sign-in again.
java.lang.Exception: No cached session.

there is no way to change the user state from SIGNED_IN to SIGNED_OUT or GUEST?

Ex2: or can we make that exceprion variable public in UserStateDetails to have access to check it? In this way I can interogatte the user state and if there is a error I can signout the users. It will be a simple check, if state==SIGNED_IN and error!=null means bad state.

With this 2 suggestions at leat the Huawei users can use the app 1h with a correct state and then after 1H when the sdk
is trying to refresh the session it will fail, I can intercept the error/new user state and I can show a relogin pop up into the app. Right now I can not do this because the state is correct and the error can not be interogated.

@tylerjroach
Copy link
Member

@lolucosmin Can you give me an estimate on number of unique devices that are experiencing this issue? Is it only showing on Huawei devices? Are some Huawei devices functioning properly?

Can you also share what (if any) inner exception exists for "No cached session"? After this PR (#3518), the exception should have an inner exception that provides an additional reason for the failure.

The trouble here is that we don't seem to be able to decrypt data stored in SharedPreferences. The only reason The SDK is working at all is because the access token is stored in memory.

With this 2 suggestions at leat the Huawei users can use the app 1h with a correct state and then after 1H when the sdk
is trying to refresh the session it will fail, I can intercept the error/new user state and I can show a relogin pop up into the app.

If this is happening on all Huawei devices, couldn't you already do this by checking if exception message is "No cached session" AND Device manufacturer is Huawei?

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Aug 19, 2024
@lolucosmin
Copy link
Author

lolucosmin commented Aug 21, 2024

@lolucosmin Can you give me an estimate on number of unique devices that are experiencing this issue? Is it only showing on Huawei devices? Are some Huawei devices functioning properly?

Can you also share what (if any) inner exception exists for "No cached session"? After this PR (#3518), the exception should have an inner exception that provides an additional reason for the failure.

The trouble here is that we don't seem to be able to decrypt data stored in SharedPreferences. The only reason The SDK is working at all is because the access token is stored in memory.

With this 2 suggestions at leat the Huawei users can use the app 1h with a correct state and then after 1H when the sdk
is trying to refresh the session it will fail, I can intercept the error/new user state and I can show a relogin pop up into the app.

If this is happening on all Huawei devices, couldn't you already do this by checking if exception message is "No cached session" AND Device manufacturer is Huawei?

Hi @tylerjroach , I don't have a specific number, but we have a lot of users which contact the app support and told us about this issue. When this users contact us we collect information about device and all of them had Huawei devices. After I saw this issue I start make some tests with this type of devices and I found that behavior which we already talk. So if you have a Huawei device which has Google Play Services on it all is fine, but when on the device is missing the refresh session after 1h is not working. As you know in Europe there are a lot of Huawei devices but Google restric them.

"Huawei was banned from Google's Android operating system because of spying concerns. The company has been accused of installing hardware on its devices that could be used to spy or intercept data, which would violate U.S. privacy laws and undermine the security at stake in our cyber world."

To answer at your question : "If this is happening on all Huawei devices, couldn't you already do this by checking if exception message is "No cached session" AND Device manufacturer is Huawei?". Yes I want to make this check and it will be fine, but check SDK , in this class UserStateDetails the exception is private so I can not access it. So if you will change the access for this variable indeed I can make that check on my side.
Screenshot 2024-08-21 082924

https://support.google.com/android/thread/29434011/answering-your-questions-on-huawei-devices-and-google-services?hl=en

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Aug 21, 2024
@tylerjroach
Copy link
Member

tylerjroach commented Aug 21, 2024

@lolucosmin That sounds reasonable. Will review this with the team and keep you updated.

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working cognito Issues with the AWS Android SDK for Cognito
Projects
None yet
Development

No branches or pull requests

3 participants