awslabs / aws-mobile-appsync-sdk-android

Android SDK for AWS AppSync.
https://docs.amplify.aws/sdk/api/graphql/q/platform/android/
Apache License 2.0
105 stars 58 forks source link

Cognito Userpools failed to get session #325

Open zhangjiancheng opened 3 years ago

zhangjiancheng commented 3 years ago

Describe the bug Friday opened the app and it runned in background thread, when Monday I make the app in front, the error occuces.

Environment(please complete the following information):

Device Information (please complete the following information):

Additional context

2021-02-01 10:16:42.186 13424-29995/? E/AndroidRuntime: FATAL EXCEPTION: Thread-237
    Process: PACKAGENAME, PID: 13424
    java.lang.RuntimeException: Cognito Userpools failed to get session
        at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.fetchToken(BasicCognitoUserPoolsAuthProvider.java:80)
        at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.getLatestAuthToken(BasicCognitoUserPoolsAuthProvider.java:86)
        at PACKAGENAME.common.aws.AWSClientFactory$1.getLatestAuthToken(AWSClientFactory.java:37)
        at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetailsForUserpools(SubscriptionAuthorizer.java:160)
        at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetails(SubscriptionAuthorizer.java:85)
        at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.requestSubscription(WebSocketConnectionManager.java:92)
        at com.amazonaws.mobileconnectors.appsync.AppSyncWebSocketSubscriptionCall.execute(AppSyncWebSocketSubscriptionCall.java:48)
        at PACKAGENAME.activities.chat.RoomMessageView.prepareOnUpdateRoomLastReadDateByRoomObserver(RoomMessageView.java:1614)
        at PACKAGENAME.activities.chat.RoomMessageView.access$3400(RoomMessageView.java:104)
        at PACKAGENAME.activities.chat.RoomMessageView$24.run(RoomMessageView.java:1465)
        at java.lang.Thread.run(Thread.java:929)
jamesonwilliams commented 3 years ago

A few suggestions of things to check:

  1. Is the user signed out when this occurs?
  2. Do you have an app/src/main/res/raw/awsconfiguration.json present in your application project? If so, does this file contain an authentication section?
  3. Perhaps your phone is locked and so the the credentials are locked? This would apply on API level 30+.
zhangjiancheng commented 3 years ago

@jamesonwilliams

A few suggestions of things to check:

  1. Is the user signed out when this occurs? No. After landing, it was placed for two days, then it occured.

  2. Do you have an app/src/main/res/raw/awsconfiguration.json present in your application project? If so, does this file contain an authentication section? Yes. I have this json file. In fact, my application run well at normal. This is a issue that comes up by chance.

  3. Perhaps your phone is locked and so the the credentials are locked? This would apply on API level 30+. When the problem occurs, my phone is awake. And my testing phone's android version is Android 10 (API29).

ukevgen commented 3 years ago

The same issue on Android 6,8,10. I don't have awsconfiguration.json file. Issue happens randomly. From Crashlytics I see that it happens 100% in background AppSync SDK Version: 3.1.1 @jamesonwilliams

wafel82 commented 2 years ago

Hello, I'm also struggling with this issue. My app is running on Android 10.

Here's the awsconfiguration.json

{
    "UserAgent": "aws-amplify-cli/0.1.0",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },

    "CognitoUserPool": {
        "Default": {
            "PoolId": "<HERE GOES POOL ID>",
            "AppClientId": "<HERE GOES CLIENT ID>",
            "Region": "<HER EGOES REGION>"
        }
    },

    "AppSync": {
        "Default": {
            "ApiUrl": "<HERE I HAVE API URL>",
            "Region": "<AND HERE IS THE REGION>",
            "AuthMode": "AMAZON_COGNITO_USER_POOLS",
            "ClientDatabasePrefix": "Backend_AMAZON_COGNITO_USER_POOLS"
        },
        "Backend_AWS_IAM": {
            "ApiUrl": "<HERE_GOES_URL>",
            "Region": "<REGION>",
            "AuthMode": "AWS_IAM",
            "ClientDatabasePrefix": "Backend_AWS_IAM"
        }
    }
}

Here's how the AWSAppSyncClient is created:

val configuration  = AWSConfiguration(applicationContext)
val cognitoUserPoolsAuthProvider = BasicCognitoUserPoolsAuthProvider(CognitoUserPool(applicationContext, configuration))
 AWSAppSyncClient.builder()
      .context(applicationContext)
      .awsConfiguration(configuration)
      .cognitoUserPoolsAuthProvider(cognitoUserPoolsAuthProvider)
      .build()

The user is signed in when the issue occurs.

First I'm getting the AppSyncSubscriptionCall.Callback::onFailure call on my active subscription. Then the Cognito Userpools failed to get session is happening. It seems that the issue occurs on low quality network, when device is loosing network connection from time to time (eg. user goes out of the WiFi range) It does not happened always - manual turning the internet connectivity off and on on the device usually does not trigger the issue.

zhangjiancheng commented 2 years ago

Any suggestions?

itslonua commented 1 year ago

https://github.com/awslabs/aws-mobile-appsync-sdk-android/blob/cb79c1217c45373f414bf52d92499943fee65101/app/src/main/java/com/amazonaws/postsapp/ClientFactory.java look into this

ncs-ankur commented 1 year ago

@itslonua are you trying to point to the PersistentMutationsCallback part in above link?

@div5yesh I'm also facing the same issue since few months. Unable to reproduce 100% time at my end but I can see many occurrences in Crashlytics logs.

I'm using: "com.amplifyframework:aws-auth-cognito:1.37.3"

I observed one thing from my Crashlytics though. Most of the times, it's either crashing immediately after login or it is crashing when user closes the app and returns to the app after few hours.

@zhangjiancheng did you find any solution for this?

ksgangadharan commented 1 year ago

Is there any resolution for this. Its happening at least once per day per user. I am also on implementation "com.amplifyframework:aws-auth-cognito:1.37.3"

Fatal Exception: java.lang.RuntimeException: Cognito Userpools failed to get session
       at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.fetchToken(BasicCognitoUserPoolsAuthProvider.java:80)
       at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.getLatestAuthToken(BasicCognitoUserPoolsAuthProvider.java:86)
       at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetailsForUserpools(SubscriptionAuthorizer.java:171)
       at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetails(SubscriptionAuthorizer.java:88)
       at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getConnectionAuthorizationDetails(SubscriptionAuthorizer.java:65)
       at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.getConnectionRequestUrl(WebSocketConnectionManager.java:391)
       at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.createWebSocket(WebSocketConnectionManager.java:131)
       at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.retryAllSubscriptions(WebSocketConnectionManager.java:307)
       at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.access$800(WebSocketConnectionManager.java:45)
       at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager$2.handleMessage(WebSocketConnectionManager.java:244)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.os.HandlerThread.run(HandlerThread.java:67)
gpanshu commented 1 year ago

Is this happening on lower version devices like <23 ? If not then I would highly recommend upgrading to Amplify V2 for all your Amplify needs including Auth and Appsync. That is built ontop of the latest kotlin sdk and redesigned entirely in Kotlin.

AnirudhWinimy commented 1 year ago

@gpanshu Based on your recommendation we did try to upgrade to V2, however we have run into other issues on V2 ( see https://github.com/aws-amplify/amplify-android/issues/2331) which is a blocker for us.

On further debugging, this issue seems to happen when the client has internet connectivity issues and when the WebSocket tries to reconnect. We were able to reproduce using the following steps:

  1. Initializing amplify sdk
  2. simulate disrupting internet connectivity or disable internet
  3. wait for ~ 5 -10 mins
  4. The above exception occurs triggering an app crash
ksgangadharan commented 1 year ago

We did try upgrading to implementation "com.amazonaws:aws-android-sdk-cognitoauth:2.64.0" . The BasicCognitoUserPoolsAuthProvider does not work at all after that. The following error is shown:

java.lang.RuntimeException: Cognito Userpools is not signed-in
at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.fetchToken(BasicCognitoUserPoolsAuthProvider.java:80)
at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.getLatestAuthToken(BasicCognitoUserPoolsAuthProvider.java:86)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetailsForUserpools(SubscriptionAuthorizer.java:171)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetails(SubscriptionAuthorizer.java:88)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getConnectionAuthorizationDetails(SubscriptionAuthorizer.java:65)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.getConnectionRequestUrl(WebSocketConnectionManager.java:391)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.createWebSocket(WebSocketConnectionManager.java:131)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.requestSubscription(WebSocketConnectionManager.java:90)
at com.amazonaws.mobileconnectors.appsync.AppSyncWebSocketSubscriptionCall.execute(AppSyncWebSocketSubscriptionCall.java:48)
gpanshu commented 1 year ago

@ksgangadharan you are using the SDK. Please try updating to amplify

ksgangadharan commented 1 year ago

@gpanshu getting the same error. So I changed to use amplify, below is my build.gradle

implementation "com.amplifyframework:core-kotlin:2.3.0"
implementation "com.amplifyframework:core:2.3.0"
implementation "com.amplifyframework:aws-auth-cognito:2.3.0"
implementation "com.amplifyframework:aws-storage-s3:2.3.0"
implementation "com.amplifyframework:aws-api:2.3.0"

implementation "com.amazonaws:aws-android-sdk-pinpoint:2.64.0"
implementation "com.amazonaws:aws-android-sdk-s3:2.64.0"
implementation 'com.amazonaws:aws-android-sdk-appsync:3.3.2'

And I am getting the same error as before:

CognitoUserSession is not valid because idToken is null.
java.lang.RuntimeException: Cognito Userpools is not signed-in
at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.fetchToken(BasicCognitoUserPoolsAuthProvider.java:80)
at com.amazonaws.mobileconnectors.appsync.sigv4.BasicCognitoUserPoolsAuthProvider.getLatestAuthToken(BasicCognitoUserPoolsAuthProvider.java:86)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetailsForUserpools(SubscriptionAuthorizer.java:171)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getAuthorizationDetails(SubscriptionAuthorizer.java:88)
at com.amazonaws.mobileconnectors.appsync.SubscriptionAuthorizer.getConnectionAuthorizationDetails(SubscriptionAuthorizer.java:65)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.getConnectionRequestUrl(WebSocketConnectionManager.java:391)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.createWebSocket(WebSocketConnectionManager.java:131)
at com.amazonaws.mobileconnectors.appsync.WebSocketConnectionManager.requestSubscription(WebSocketConnectionManager.java:90)
at com.amazonaws.mobileconnectors.appsync.AppSyncWebSocketSubscriptionCall.execute(AppSyncWebSocketSubscriptionCall.java:48)
gpanshu commented 1 year ago

@ksgangadharan just to understand your issue you login then after a period of inactivity call fetchAuthSession and you get this error ? If not then please provide reproduction steps.

ksgangadharan commented 1 year ago

@gpanshu I login, and then I try to create the AWSAppSyncClient object

val cognitoUserPool = CognitoUserPool(context, AWSConfiguration(context))
val provider = BasicCognitoUserPoolsAuthProvider(cognitoUserPool)

val client = AWSAppSyncClient.builder()
    .context(context)
    .awsConfiguration(awsConfig)
    .cognitoUserPoolsAuthProvider(provider)
    .okHttpClient(okHttpClientBuilder.build())
    .s3ObjectManager(getS3ObjectManager(context))
    .build()

Note, that I did manage to make this work temporarily by replacing the provider with this code:

val provider = CognitoUserPoolsAuthProvider { (session as? AWSCognitoAuthSession)
                    ?.userPoolTokensResult?.value?.idToken }

where session was retrieved using Amplify.Auth.fetchAuthSession(). However this code has issues when the app is running for a long time

gpanshu commented 1 year ago

What are the issues you are having with fetchAuthSession after the code has been running for a long time?

ksgangadharan commented 1 year ago

@gpanshu there is no issue with fetchAuthSession. Problem is that fetchAuthSession is a coroutine and trying to integrate it with CognitoUserPoolsAuthProvider (which is a non coroutine code) is not straightforward and is prone to side effects

That's the reason why we need the BasicCognitoUserPoolsAuthProvider to work. Note that this code was working earlier when the amplify version was 1.37.3

gpanshu commented 1 year ago

I see that you are using both the AWS Java SDK and Amplify together. They are not meant to be used together. Is there a use case you are trying to solve by using both of them. Have you tried only using Amplify V2 for Android to see if that solves your problem.

ksgangadharan commented 1 year ago

There are 2 AWS sdk libraries that I am using, 1) Pinpoint library for registering for FCM notification, I don't see an alternative to that in the V2 amplify lib, and 2) the S3 library, and this is needed to attach a S3Object manager to the app sync client (refer AWSAppSyncClient.builder().s3ObjectManager(...)). I don't think there is an alternative for that .

Coming back to the original issue, what is the alternative for BasicCognitoUserPoolsAuthProvider. This is not referring to any of the AWS SDK classes, and it does not work

iolandarosa7 commented 6 months ago

I am also having the same issue using app sync with the latest amplify version. I am setting authentication with cognitoUserPoolsAuthProvider using the BasicCognitoUserPoolsAuthProvider.

This was working fine with latest amplify version 1.37.5 but does not work anymore with 2.14.9. The token is always null. Amplify session object that retrieves tokens has changed and I am not sure if this is related with that situation

tjleing commented 6 months ago

@iolandarosa7 the 1.x version of Amplify depends on the AWS SDK for Android, which is compatible with the AppSync SDK here. However, the 2.x version of Amplify depends on the AWS SDK for Kotlin, which is not compatible with this library.

iolandarosa7 commented 5 months ago

@tjleing Thanks for your answer. For now, I implemented a custom auth provider that overrides the getLatestAuthToken method. It seems that with this app sync works fine. Anyway I will probably need to drop using app sync sdk in the future, and start using methods from Amplify GraphQL library.

Thanks