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 1 year ago

@Jordan-Nelson yes, the lack of support for 21 is the only blocker we have encountered in the tests we conducted. Ideally, we should support 21 because cutting off even a "small" number of users is never good and can bring us problems. Thank you in advance.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. Do you have any updates?

Jordan-Nelson commented 1 year ago

@brunovsiqueira I don't have an update yet. There are a couple dependencies that require level 23/24. We are still discussing if we could support lower API levels.

Jordan-Nelson commented 1 year ago

Just wanted to let you know that we are still looking into this. I will post here when I have an update.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. Thanks for the update. Looking forward to hear back from you.

gopbarbosa commented 1 year ago

I hope this message finds you well. I wanted to address the issue reported by @brunovsiqueira . I recently updated the library to version 1.10.0, but some users are still experiencing the same problem. Unfortunately, I don't have enough data at the moment to determine if the error rate has increased or decreased. I am actively seeking additional solutions and will continue to closely monitor the situation.

Thank you for your understanding, and any further feedback would be greatly appreciated.

Jordan-Nelson commented 1 year ago

@GarbielBarbosa thanks for letting us know. If you are able to get enough info to reproduce this issue, please let us know so that we can investigate further. If there is any info you can provide (devices, OSs, stack traces, etc.) that you think might help, please do provide it.

Jordan-Nelson commented 1 year ago

@GarbielBarbosa Just to confirm, did you mean version 1.1.0?

gopbarbosa commented 1 year ago

@Jordan-Nelson, I apologize for the mistake. I am using version 1.1.0 of the library. I am unable to reproduce the error on my devices; the errors are only reported by my users. Additionally, I am able to track them through Crashlytics/Firebase. Below is the structure of my code.

Future<void> hasUser() async {
    final ILocalStorage storage = Modular.get();
    final User? user = await storage.getUser();

      // verifica se o usuário está logado.
      try {
        await Amplify.Auth.getCurrentUser();
      } catch (e) {
        showAlertErrorLogin(code: '1000');
        await goToLogin();
        return;
      }

      // Retorna os tokens do cognito e os fixa no usuário
      try {
        final session = await Amplify.Auth.getPlugin(
          AmplifyAuthCognito.pluginKey,
        ).fetchAuthSession();
        if (session.isSignedIn) {
          storage.user.acessToken = session.userPoolTokensResult.value.accessToken.toJson();
          storage.user.idToken = session.userPoolTokensResult.value.idToken.toJson();
          storage.user.refreshToken = session.userPoolTokensResult.value.refreshToken;
        }
      } catch (e, stackTrace) {
        await FirebaseCrashlytics.instance.recordError(e, stackTrace, reason: 'Erro ao logar fetchAuthSession');
        AnalyticsFunctions.saveLog('Erro ao logar fetchAuthSession', {'error': e.toString()});
        try {
          final session = await Amplify.Auth.getPlugin(
            AmplifyAuthCognito.pluginKey,
          ).fetchAuthSession();
          if (session.isSignedIn) {
            storage.user.acessToken = session.userPoolTokensResult.value.accessToken.toJson();
            storage.user.idToken = session.userPoolTokensResult.value.idToken.toJson();
            storage.user.refreshToken = session.userPoolTokensResult.value.refreshToken;
          }
        } catch (e) {
          await FirebaseCrashlytics.instance.recordError(e, stackTrace, reason: 'Erro ao logar fetchAuthSession 2');
          AnalyticsFunctions.saveLog('Erro ao logar fetchAuthSession', {'error': e.toString()});
          showAlertErrorLogin(code: '1002');
          await goToLogin();
          return;
        }
      }

      // Caso o id token do usuário ou o email esteja vazio o usuário é deslogado.
      if (storage.user.idToken == null || storage.user.email == null) {
        await Amplify.Auth.signOut(
          options: const SignOutOptions(),
        );
        showAlertErrorLogin(code: '1003');
        await goToLogin();
        return;
      }

      await goToHome();
    }
  }

Would this type of StackTrace be useful?

Captura de Tela 2023-05-27 às 17 19 15
Jordan-Nelson commented 1 year ago

@GarbielBarbosa The stack trace indicates the error is coming from the method channel implementation of fetchAuthSession. Version 0.x of Amplify wraps Amplify iOS and Android using method channels. This implementation is no longer present in version 1.x of Amplify is it has been re-written in Dart. Is it possible that the users that are experiencing this are using a version of your app that still uses version 0.x of Amplify?

gopbarbosa commented 1 year ago

Hi, @Jordan-Nelson! I'd like to confirm if the correct method to obtain the tokens is as follows:

  final session = await Amplify.Auth.getPlugin(
      AmplifyAuthCognito.pluginKey,
    ).fetchAuthSession();
    if (session.isSignedIn) {
      storage.user.acessToken = session.userPoolTokensResult.value.accessToken.toJson();
      storage.user.idToken = session.userPoolTokensResult.value.idToken.toJson();
      storage.user.refreshToken = session.userPoolTokensResult.value.refreshToken;
    }

Our builds are performed through a pipeline. I truly believe that the version has already been updated with the new library version.

Please review and confirm if my understanding is correct. If not, please clarify the correct method. Thank you in advance for your assistance!

gopbarbosa commented 1 year ago

Hello, @Jordan-Nelson!

Upon conducting a new search, I noticed that I obtained an incorrect build stack trace that used an outdated library. Please find below the new error stack trace. Captura de Tela 2023-05-29 às 11 30 53 Captura de Tela 2023-05-29 às 11 30 38

It appears to be a connection error, but according to the users, they are able to proceed with the login normally immediately after this error, indicating the need for a valid internet connection.

I'm available for further information or clarification.

Jordan-Nelson commented 1 year ago

@GarbielBarbosa - Yes, fetchAuthSession is the correct way to obtain the tokens.

It could be that the users experiencing this have a spotty network connection that is causing only some requests to fail. You can handle the network exception case. A network exception indicates that the user's access/id tokes have expired, but the refresh token may still be valid (there is no way to determine the validity of the refresh token while offline). In the Authenticator UI component this case is handled as a valid session while the user is offline. Once they come back online if the refresh token has expired they will then be direct to sign in again. You can see how that is handled below.

https://github.com/aws-amplify/amplify-flutter/blob/7949173db4ce50d75afa18e61f5ded2784899de1/packages/authenticator/amplify_authenticator/lib/src/services/amplify_auth_service.dart#L204-L224

If you would like further assistance can you please open a new issue since it does not appear that the exception you are seeing is that same as what was reported in the original issue.

gopbarbosa commented 1 year ago

@Jordan-Nelson,

I kindly request your assistance in reviewing the issue https://github.com/aws-amplify/amplify-flutter/issues/3130. I would be immensely grateful if you could take a look at it and provide your analysis.

Thank you for your attention and support.

ilyasarafath commented 1 year ago

getting same issue for me its getting after signIn accessing storage upload SessionExpiredException { E/flutter (13937): "message": "The AWS credentials could not be retrieved", E/flutter (13937): "recoverySuggestion": "Invoke Amplify.Auth.signIn to re-authenticate the user", E/flutter (13937): "underlyingException": "NotAuthorizedException {\n message=Token is not from a supported provider of this identity pool.,\n}" E/flutter (13937): }

Jordan-Nelson commented 1 year ago

@ilyasarafath the underlying exception in the logs you shared is different than what has been shared for this issue. I think it is likely a different issue. Can you open a new issue so that we can gather all the details about your issue?

brunovsiqueira commented 1 year ago

Hi there. @Jordan-Nelson have you guys discussed about downgrading the minSdkVersion? We need to migrate to check if the issue persists, but we can't do so without supporting all users.

Jordan-Nelson commented 1 year ago

Hi @brunovsiqueira - Apologies that this has been taking a while. There are two blockers from supporting these API levels that we are discussing internally:

  1. EncryptedSharedPreferences, used within Auth (as well as other categories), has stable support for 23+
  2. Amplify Android (used within a couple non-auth categories) supports 24+

It is unlikely that we will be able to support API 21/22 because of the blocker on EncryptedSharedPreferences. We are still discussing support for 23.

If we were able to support 23, would this allow you to adopt Amplify flutter v1 or would lack of support for 21/22 still be a blocker?

Jordan-Nelson commented 1 year ago

@brunovsiqueira - I just wanted to follow up with you and see if supporting API level 23 would unblock you from upgrading. As I had mentioned, I don't think supporting levels 21 & 22 will be possible because of the blocker on EncryptedSharedPreferences.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. Thank you for the follow-up.

Unfortunately, we cannot upgrade the minSdkVersion to 23. We currently have 2,000 active users on API 21 and 22, and for now we cannot stop supporting them.

Jordan-Nelson commented 1 year ago

Hi @Jordan-Nelson. Thank you for the follow-up.

Unfortunately, we cannot upgrade the minSdkVersion to 23. We currently have 2,000 active users on API 21 and 23, and for now we cannot stop supporting them.

Just to confirm, do you mean API 21 and 22?

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson. Thank you for the follow-up. Unfortunately, we cannot upgrade the minSdkVersion to 23. We currently have 2,000 active users on API 21 and 23, and for now we cannot stop supporting them.

Just to confirm, do you mean API 21 and 22?

Exactly. Sorry for the confusion. I have just updated my comment.

Jordan-Nelson commented 1 year ago

Okay. We are exploring supporting API 23. If you would like to see 21/22 supported in version 1.x, would you be willing to open a feature request? We can use that to track interest in support for those API levels.

Jordan-Nelson commented 1 year ago

@brunovsiqueira - I think it makes sense to close this issue out as we believe this has been resolved in v1, and do not plan to address it in v0. If you would like, we can open a feature request to track interest in supporting a lower API level on Android.

Jordan-Nelson commented 1 year ago

@brunovsiqueira - I am going to close out this issue. Please feel free to open a request for supporting a lower API level on Android in v1. Please let me know if you have any questions.

brunovsiqueira commented 1 year ago

Hi @Jordan-Nelson @dnys1, how are you?

Our app is currently undergoing migration to support API level 23 (minSdkVersion 23). Is it possible for Amplify Flutter to also support API level 23? If so, we can proceed with migrating to version 1.x.x. This would be greatly appreciated by our team at BTG Pactual.

Additionally, the need to support Amplify versions earlier than 1.0.0 has become a significant challenge due to its dependency on aws_common, which itself relies on http version 0.13.4. Consequently, we are unable to update any dependencies that have moved to http version 1.x.x.

Jordan-Nelson commented 1 year ago

Hi @brunovsiqueira - You are look for Amplify V1 to support Android API level 23+ for the Auth category only, correct? You had previously asked about API levels 21/22. Are you only looking for API level 23+?

Could you open a new feature request for this, and include those details? Thanks

brunovsiqueira commented 1 year ago

Hi @brunovsiqueira - You are look for Amplify V1 to support Android API level 23+ for the Auth category only, correct? You had previously asked about API levels 21/22. Are you only looking for API level 23+?

Could you open a new feature request for this, and include those details? Thanks

Thanks for the fast answer. Yes, I am looking for amplify_flutter, amplify_auth_cognito and amplify_core to support API 23. These are the dependencies we have.

I am going to open a feature request.

brunovsiqueira commented 1 year ago

@Jordan-Nelson I have just created the feature request: https://github.com/aws-amplify/amplify-flutter/issues/3739.