aws-amplify / amplify-flutter

A declarative library with an easy-to-use interface for building Flutter applications on AWS.
https://docs.amplify.aws
Apache License 2.0
1.33k stars 248 forks source link

Users getting session expired right after sign in #1271

Closed brunovsiqueira closed 1 year ago

brunovsiqueira commented 2 years ago

Hi there.

We have two android users in production which are not being able to use our app because Amplify returns session expired right after signIn when we call fetchAuthSession.

Inspecting this user's logs, what I see is the following:

1- We check user session by calling (Amplify.Auth.getCurrentUser(), Amplify.Auth.fetchAuthSession) when the app is opened. We consider session expired if InvalidStateException or SessionExpiredException is thrown and then we call Amplify.Auth.signOut() if session has expired. In the mentioned case, this user session is considered expired and he is logged out.

2- After that, the user called signIn successfully and "isSignedIn" flag returned true.

3- Right after signIn (sequentially), Amplify.Auth.fetchAuthSession is called in order to get user token (JWT) to call one of our APIs. When fetchAuthSession is called, this is the result according to the logs: (message: Your session has expired., recoverySuggestion: Please sign in and reattempt the operation., underlyingException: null) Because user session has expired right after signIn, the user is not able to get the token and consequently is not able to consume none of our APIs.

This behavior is completely weird since the user has just logged in and is getting session expired. I was not able to reproduce it.

Since we have production users facing this problem, can anyone please help me understand/solve the problem?

brunovsiqueira commented 2 years ago

@haverchuck @Amplifiyer

fjnoyp commented 2 years ago

Hi @brunovsiqueira

Have some followup questions to better help you here:

1) Is this Android only or also on iOS? 2) Are you able to reproduce this on your side when deploying your app to an Android device or emulator? 3) Which Amplify CLI version are you using?

4) We have a similar issue, it's a bit long and we're still working on resolution on it. For them, calling await getCurrentUser() right after await signIn() throws a SignedOutException - can you verify if you have the same behavior?

brunovsiqueira commented 2 years ago

Hi @fjnoyp

  1. Only android AFAIK. In my app logs I only see this problem for Android devices.
  2. No, I wasn't.
  3. Amplify config:

    String amplifyConfig = ''' {
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "UserAgent": "aws-amplify-cli/0.1.0",
                "Version": "0.1.0",
                "IdentityManager": {
                    "Default": {}
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "${getPoolIdForEnv()}",
                        "AppClientId": "${getAppClientIdForEnv()}",
                        "Region": "${getRegionForEnv()}"
                    }
                },
                "Auth": {
                    "Default": {
                        "authenticationFlowType": "USER_SRP_AUTH"
                    }
                }
    
            }
        }
    }
    }''';
  4. I tested here and the answer is no. getCurrentUser right after signIn works properly.

Also, my amplify versions:

amplify_auth_cognito: 0.2.10
amplify_core: 0.2.10
amplify_flutter: 0.2.10
haverchuck commented 2 years ago

@brunovsiqueira Do you know which devices these are occurring on?

brunovsiqueira commented 2 years ago

@haverchuck Samsung SM-G973F (Galaxy S10), SM-N770F (Galaxy Note 10 lite).

Just letting you guys know, the same user who had this problem on SM-N770F (Galaxy Note 10 lite) tested on SM-N950F (Galaxy Note 20 FE) and it worked. So it seems to be linked with Samsung devices (?).

Additionaly, a user who had the same problem but only reinstalled the app, continue having the problem.

dnys1 commented 2 years ago

Could this explain the behavior you're seeing?

https://github.com/aws-amplify/amplify-android/issues/1485#issuecomment-915691808

brunovsiqueira commented 2 years ago

Hi @dnys1.

One of our users who reported the problem reinstalled the app from scratch. The behavior that we see in our logs is even stranger:

1- Because he reinstalled the App, he had no session so no SessionExpired was thrown. 2- He tried to sign in (in theory by the first time, since he reinstalled the app) and he signedIn with "success" (which is confirmed if we look at cognito console). By success I mean no exception was thrown when calling the signIn method.

Screen Shot 2022-01-19 at 18 54 52

3- Right after signIn we call fetchAuthSession to get JWT token and it throw SessionExpiredException.

One thing that may be linked to the issue you mentioned is the fact that no exception is thrown when we call signIn, but instead it is thrown we try to fetch user session by calling fetchAuthSession (not sure if this behavior is expected, maybe yes).

I don't think the issue you mentioned explains our problem, since even reinstalling the app the user gets SessionExpired when fetching session right after a "successful" sign in.

dnys1 commented 2 years ago

Hmm okay, I will look into it more tomorrow. Does the object returned from the signIn call provide any info?

I did try to reproduce this both in an emulator (Pixel) and a physical device (Galaxy S8) and for after the access token expired and after the access & refresh tokens expired. For all cases, I got the expected behavior. Unfortunately, I'm not sure what else to test for this.. these kinds of bugs are obviously very difficult to triage.

brunovsiqueira commented 2 years ago

Actually I don't have access to the signIn object in my logs.

I think I am going to try to create an emulador which has same configurations of the mentioned devices (S10 and Note 10). I agree this bugs are very hard to reproduce.

brunovsiqueira commented 2 years ago

@dnys1 were you able to figure something out?

dnys1 commented 2 years ago

Unfortunately, I haven't made any more progress @brunovsiqueira - I'm at a bit of a loss. Would you be willing to open a ticket with the amplify-android team with the same information? It's possible they may have some more insight as to what could be happening.

bwhiteTP commented 2 years ago

We are having this problem as well.

brunovsiqueira commented 2 years ago

@dnys1 yes, I can. But it is happening in the flutter plugin.

fjnoyp commented 2 years ago

Indeed. The Amplify Flutter plug-in's functionality is built on top of Amplify Android which might be the root source of the problem. Just to confirm, the issue you encounter does not happen on iOS?

brunovsiqueira commented 2 years ago

@fjnoyp I haven't seen any of this issue' logs on iOS, so I assume it is not happening on iOS but I am not totally sure.

brunovsiqueira commented 2 years ago

We are having this problem as well.

@bwhiteTP is this problem happening for you only on Android as well? Do you have any information about the devices where it is happening?

bwhiteTP commented 2 years ago

This does not happen to us on iOS, only Android. It also only seems to happen with sign in with email. It does't happen on sign up and it doesn't happen every time. The way I've reproduced it:

  1. Sign in with SSO
  2. Intentionally Sign out
  3. Sign up with email
  4. Intentionally Sign out
  5. Sign in with email - Get signed out immediately

After I sign in with email and getting signed out a few more times it will just start working randomly. So the issue seems to fix itself after several tries.

brunovsiqueira commented 2 years ago

We don't use SSO and we only sign in our user using "username", not email.

@bwhiteTP do you know in which device the error is happening?

brunovsiqueira commented 2 years ago

Complete logs:

SessionExpiredException(message: Your session has expired., recoverySuggestion: Please sign in and reattempt the operation., underlyingException: null)
#0      AmplifyAuthCognitoMethodChannel.fetchAuthSession (package:amplify_auth_cognito\/method_channel_auth_cognito.dart:246)
<asynchronous suspension>
#1      AmplifyAuthCognito.fetchAuthSession (package:amplify_auth_cognito\/amplify_auth_cognito.dart:121)
<asynchronous suspension>
#2      SessionService._fetchSession (package:btg_auth_core\/src\/services\/session_service.dart:23)
<asynchronous suspension>
#3      SessionService.getAccessJWTToken (package:btg_auth_core\/src\/services\/session_service.dart:34)
<asynchronous suspension>
#4      BasicAPI.getHeaders (package:btg_auth_core\/src\/services\/api\/basic_api.dart:27)
<asynchronous suspension>
#5      BasicAPI.httpGet (package:btg_auth_core\/src\/services\/api\/basic_api.dart:136)
<asynchronous suspension>
#6      GkRemoteDatasourceImpl.getSelfUser (package:btg_auth_core\/src\/datasources\/gk_remote_datasource.dart:23)
<asynchronous suspension>
#7      UserServiceImpl.getSelfUser (package:btg_auth_core\/src\/services\/user_service_impl.dart:28)
<asynchronous suspension>
#8      UserViewModel.fetchCurrentUserData (package:btg_auth_core\/src\/viewmodels\/user_viewmodel.dart:33)
<asynchronous suspension>
#9      LoginViewModel.login (package:btg_login\/src\/viewmodels\/login_viewmodel.dart:218)
<asynchronous suspension>
#10     _LoginPasswordPageState.build.<anonymous closure> (package:btg_login\/src\/pages\/login_password_page.dart:72)
<asynchronous suspension>
fjnoyp commented 2 years ago

Hi @brunovsiqueira @bwhiteTP thanks for sharing that information. Based on the information you've shared this sounds like an issue that is coming from the underlying Amplify Android library.

Can you do what @dnys1 suggested and create an issue on the Amplify Android git repo?

https://github.com/aws-amplify/amplify-android/issues

brunovsiqueira commented 2 years ago

I have created the issue on the Amplify Android git repo: https://github.com/aws-amplify/amplify-android/issues/1635.

fjnoyp commented 2 years ago

Great thank you. We can monitor from there.

dorontal commented 2 years ago

Possibly related to this issue: https://github.com/aws-amplify/amplify-flutter/issues/1204 - especially if you're using attributes for access control. We found out that setting up attributes for access control causes users to get a session expired exception right after signing in on Android. A new issue was opened for that here: https://github.com/aws-amplify/amplify-cli/issues/9747

brunovsiqueira commented 2 years ago

Just an update: it's happening in both iOS and Android. Also, it is happening a lot. Seems that even reinstalling the app the SessionExpiredException keep being thrown right after signIn. This issue is highly critical and I think it must be given the properly urgency.

brunovsiqueira commented 2 years ago

I think the issue my users are having is the same. Seems that it happens in both login/relogin and also in both platforms (Android and iOS). By looking at out logs, it is happening with several users. These are the exceptions I see this users are getting:

SessionExpiredException(message: Session expired could not fetch user sub, recoverySuggestion: Invoke Auth.signIn to re-authenticate the user, underlyingException: null)

SignedOutException(message: There is no user signed in to retreive user sub, recoverySuggestion: Call Auth.signIn to sign in a user and then call Auth.fetchSession, underlyingException: null)
brunovsiqueira commented 2 years ago

Looking at an iOS user specific behavior: 1- User is logging in normally and using our app (I can see by his logs) 2- Following method is called and returns true because SessionExpiredException is thrown:

Future<bool> isSessionExpired() async {
    try {
      await _fetchSession();
      return false;
    } on SignedOutException {
      return false;
    } on SessionExpiredException {
      return true;
    } on InvalidStateException {
      return true;
    } on AuthException {
      rethrow;
    }
  }

3- By determining that session is expired, we call: "await Amplify.Auth.signOut()" in order to try to signout an user which his session expired. 4- After it user signs in "normally" (without throwing an exception) by entering his username and password and the app calls await Amplify.Auth.signIn. We check isUserSignedIn flag and it also returns true. 5- Right after it, we call "await Amplify.Auth.fetchAuthSession" and it throws SignedOutException. By throwing this exception, we are unable to get the access token.

brunovsiqueira commented 2 years ago

In android, the behavior changes depending on the user. One thing never changes: user gets SessionExpiredException right after signIn (on iOS seems that he gets SignedOutException). We have some users who got SessionExpiredException even in their first signIn attempts which is really sad.

brunovsiqueira commented 2 years ago

Digging deep into the problem, I found out a pattern. The users' devices who gets this problem right after signIn are not being listed in "Device tracking log" even though their events are shown as "Sign-in passed" in "User event history". Look at this user: 158589821-edffcfde-fbd1-4600-a012-50bc78bbb716

If you see, the user tried to log in using two different devices: an iPhone and a SM-G9600 (Android). However, the only device which is listed in "Device tracking log" is the iPhone. It is a pattern, all user who had this problem I can observe the same behavior: I see the sign in event in "User event history" but I don't see the device which I see the logs in "Device tracking log". @dnys1 @fjnoyp this may help you guys solve this problem.

My device tracking configuration is set as "Always remember": MicrosoftTeams-image (33)

My "advanced security" feature is enabled: MicrosoftTeams-image (34)

brunovsiqueira commented 2 years ago

Look at a normal user behavior (my user): 158654689-2faf1e94-5bbf-4ab0-8fbd-d95b7bb609f4

If you see, every time I make a successful signIn after reinstalling the app, he register my device in the "Device tracking log".

Now look at this user behavior. He said he always uninstall apps for security reasons. He used to be able to sign in our app weeks ago. Now when he signs in after reinstalling the app (in the last attempts), no new device is added to the "Device tracking logs" even though he signed in "successfully" (sign in passes but SessionExpired is thrown when getting credentials).

158655617-d7635e43-ef99-447c-a952-d0dc34abdd69

gpanshu commented 2 years ago

Session expired event will be thrown on expired token fetch inside fetchAuthSession after this PR is merged in for Android.

Jordan-Nelson commented 2 years ago

Hello everyone - We have been unable to reproduce this issue. However, I am going to label this as a bug since the info provided indicates there may be a race condition present.

We have recently released a new developer preview version of the Auth category (amplify_flutter v1.0.0-next.0). This new version is a full re-write of the auth category in dart. While the primary purpose of this re-write was to add support for Web and Desktop, we also implemented a new design using state machines that is intended to solve issues such as race conditions. You can read more about the developer preview release in the blog post and docs.

I believe this will address the issue described above. If you are willing to experiment with this new version while it is in dev-preview we would appreciate any feedback you have.

I will provide an update on this ticket once this version is out of dev-preview and is ready for production use.

Let me know if you have any questions.

brunovsiqueira commented 2 years ago

Hi @Jordan-Nelson. Any plans to make the new version of amplify auth stable?

Jordan-Nelson commented 2 years ago

@brunovsiqueira - Unfortunately I don't have a timeline at the moment. There are a few items preventing the new version of auth from being considered stable. One of those items is that the new version of auth is incompatible with amplify analytics on Android. I can update this issue when I have more info. I appreciate your patience.

petreikis commented 2 years ago

We are also facing the same issue. @brunovsiqueira, did you find any workarounds to mitigate it?

brunovsiqueira commented 2 years ago

@petreikis I didn't. I think there is no possible workarounds. Amplify lib is the one that should deal with it. @Jordan-Nelson Any plans to release the new version?

wiktoriasobczyk commented 2 years ago

I'm waiting for the amplify lib update, mby it would be working better in the next version 🤷 😢

Jordan-Nelson commented 1 year ago

@brunovsiqueira - I don't have a timeline on when the dev-preview will be considered stable. The latest version is on pub: https://pub.dev/packages/amplify_flutter/versions/1.0.0-next.3

@petreikis @wiktoriasobczyk - Are you able to reproduce this consistently? If so, please do let me know. The first step towards resolving this would be reproducing it consistently. Unfortunately we have not been able to do that yet.

Jordan-Nelson commented 1 year ago

@petreikis @wiktoriasobczyk - Have either of you been able to reproduce this or are you also observing it in logs? If you are able to provide steps to reproduce, that would help us find the cause of the issue in the latest stable version.

brunovsiqueira commented 1 year ago

It is still happening with some users. I can't reproduce but it does not mean that the problem does not exist. The only thing I can do is to wait for the new lib release.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. This issue is still affecting production users. Is there any plans for the mentioned release candidate to become stable? I see you guys are still working on that, but I am a little bit afraid of updating our app to a non stable version.

Jordan-Nelson commented 1 year ago

@brunovsiqueira - we are aiming to have a stable version out very soon. I'll let you know when it is available.

Jordan-Nelson commented 1 year ago

@brunovsiqueira - v1.0.0 of Amplify Flutter is now stable. We believe that this issue has been addressed. Would you please upgrade to the latest version and let us know if you still observe this issue?

This release also includes web and desktop support for Auth, API, Analytics, and Storage. You can see the list of new features and bug fixes in the release notes, and see more details on how to migrate in the upgrade guide.

brunovsiqueira commented 1 year ago

Thanks a lot @Jordan-Nelson. We are working in the migration and I let you guys know as soon as I have an update.

Jordan-Nelson commented 1 year ago

Hello @brunovsiqueira - Just checking in to see if you have been able to upgrade to v1. Please let me know if you are facing any issues. Thanks.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. While we were migrating we realized that the minSdkVersion is 24 and unfortunately we have thousands of users below this SDK version, what makes us not to migrate.

Is there any reason for upgrading the minSdkVersion? Is there any possibility to downgrade?

Jordan-Nelson commented 1 year ago

@brunovsiqueira - Correct, the minSdk was bumped from 21 to 24. There were a few reasons for this. What is the min version you currently support? Do you know roughly how many users you have at each version below 24?

brunovsiqueira commented 1 year ago

@Jordan-Nelson We support minSdkVersion 21. In the last 90 days: Around 3k users in 23 Around 200 users in 22 and 21.

Is there any chance to downgrade the minSdkVersion in this new version? I think the biggest problem is with Android 6 (API 23).

Jordan-Nelson commented 1 year ago

@brunovsiqueira - Are you using other categories from Amplify besides Auth (API, Analytics, DataStore, Storage, or Notifications)?

brunovsiqueira commented 1 year ago

@Jordan-Nelson only auth at this time.

Jordan-Nelson commented 1 year ago

@brunovsiqueira - I will discuss the possibility of supporting 23 with the team and get back to you. Is this your only blocker from migrating to v1 at this time?