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

Tokens are invalid, please sign-in again after call AWSMobileClient.getInstance().getTokens(callback) #873

Closed
tvanmanh opened this issue Apr 5, 2019 · 18 comments
Assignees
Labels
bug Something isn't working closing soon Issue will auto-close if there is no additional activity within 7 days. mobile client Issues with AWS Mobile's client-side Cognito wrapper pending-community-response Issue is pending response from the issue requestor

Comments

@tvanmanh
Copy link

tvanmanh commented Apr 5, 2019

Describe the bug
I have already signed in and then I kill app and open app again.
In my plash screen I call API AWSMobileClient.getInstance().initialize() and check the user state is "SIGNED_IN".
After that I go to next step, call my backend API which needs token using AWSMobileClient.getInstance().getTokens(new Callback()) after i call that API. I got user state is " SIGNED_OUT_USER_POOLS_TOKENS_INVALID" and This call blocked the thread forever don't return token or any error.

I know that the token will expire after 1 hour but I have already signed in. Just kill my app and open app again How can i got SIGNED_OUT_USER_POOLS_TOKENS_INVALID after call get token.

I resolved it by add UserStateListener after getting SIGNED_OUT_USER_POOLS_TOKENS_INVALID i will sign in again but should I do that every time I kill app and open again ?

To Reproduce

Code and logs
`My code in plash screen: 
AWSMobileClient.getInstance().initialize(getApplicationContext(), new Callback<UserStateDetails>() {
                    @Override
                    public void onResult(UserStateDetails userStateDetails) {
                        Log.i("MYLOG", "Result: " + userStateDetails.getUserState());
                        initializeSingletonClass();

                        if (userStateDetails.getUserState() == UserState.SIGNED_IN) {
                            routeToAppropriatePage(ActMain.class);
                        } else {
                            routeToAppropriatePage(ActLoginOption.class);
                        }
                    }

                    @Override
                    public void onError(Exception e) {
                        Log.e(TAG, "MYLOG", e);
                        routeToAppropriatePage(ActLoginOption.class);
                    }
                }
        );
        AWSMobileClient.getInstance().addUserStateListener(new UserStateListener() {
            @Override
            public void onUserStateChanged(UserStateDetails details) {
                switch (details.getUserState()) {
                    case GUEST:
                        Log.i("MYLOG", "user is in guest mode");
                        break;
                    case SIGNED_OUT:
                        Log.i("MYLOG", "user is signed out");
                        break;
                    case SIGNED_IN:
                        Log.i("MYLOG", "user is signed in");
                        break;
                    case SIGNED_OUT_USER_POOLS_TOKENS_INVALID:
                        Log.i("MYLOG", "need to login again");
                        break;
                    case SIGNED_OUT_FEDERATED_TOKENS_INVALID:
                        Log.i("MYLOG", "user logged in via federation, but currently needs new tokens");
                        break;
                    default:
                        Log.e("MYLOG", "unsupported");
                }
            }
        });

I put it onResume function 

My code when i call get token: 
    protected Single<String> getToken() {
        return Single.create((subscribe) -> {
            AWSMobileClient.getInstance().getTokens(new Callback<Tokens>() {
                @Override
                public void onResult(Tokens result) {
                    Log.d(TAG, "getTokens onResult: access");
                    subscribe.onSuccess(result.getAccessToken().getTokenString());
                }

                @Override
                public void onError(Exception e) {
                    Log.d(TAG, "getTokens onError: " + e);
                    subscribe.onError(e);
                }
            });
        });
    }
log: 
when i go to plash screen: 
2019-04-05 16:11:23.495 31573-31784/ I/MYLOG: Result: SIGNED_IN
2019-04-05 16:11:23.674 31573-31842/ I/MYLOG: user is signed in
after i call get token: 
2019-04-05 16:11:23.495 31573-31784/ I/MYLOG: Result: SIGNED_IN
2019-04-05 16:11:23.674 31573-31842/ I/MYLOG: user is signed in
2019-04-05 16:11:24.369 31573-31916/ I/MYLOG: need to login again`

Environment Information (please complete the following information):

  • AWS Android SDK Version: 2.13.0
  • Device: Samsung, xiaomi, Redmi
  • Android Version: 7.1.1, 8.1.0

I'm waiting for your feedback.
Thanks

@rohandubal rohandubal added the mobile client Issues with AWS Mobile's client-side Cognito wrapper label Apr 8, 2019
@BillBunting
Copy link
Contributor

@tvanmanh There are significant bugs in 2.13.0 (and 2.12.x) with token management if using AWSMobileClient drip in UI, and as as a result the AWSMobieClient drop in UI will not refresh tokens properly and other related issues. I was able to get it working in 2.13.1.

You wrote: "I resolved it by add UserStateListener after getting SIGNED_OUT_USER_POOLS_TOKENS_INVALID i will sign in again but should I do that every time I kill app and open again ?"

I do exactly that in my code taken from the sample code and this should work in 2.13.1.

                switch (userStateDetails.getUserState()){
                    case SIGNED_IN:
                        Log.i("onUserStateChanged", "SIGNED_IN: ");
                        initializeAndLoadData();
                        break;
                    case SIGNED_OUT:
                        Log.i("onUserStateChanged", "SIGNED_OUT:");
                        showSignIn();
                        break;
                    case SIGNED_OUT_USER_POOLS_TOKENS_INVALID:
                        Log.i("onUserStateChanged", "SIGNED_OUT_USER_POOLS_TOKENS_INVALID: need to login again.");
                        showSignIn();
                        break;
                    case SIGNED_OUT_FEDERATED_TOKENS_INVALID:
                        Log.i("onUserStateChanged", "SIGNED_OUT_FEDERATED_TOKENS_INVALID: need to login again.");
                        showSignIn();
                        break;
                    case GUEST:
                        Log.i("onUserStateChanged", "GUEST.");
                        showSignIn();
                        break;
                    default:
                        Log.i("onUserStateChanged", "unsupported, default.");
                        showSignIn();
                        break;
                }
            }
        };

where showSignIn() is calls

AWSMobileClient.getInstance().showSignIn(
                        MainActivity.this,
                        SignInUIOptions.builder()
                                .nextActivity(MainActivity.class)
                                .canCancel(false)
                                .build(),
                        new Callback<UserStateDetails>() {
                            @Override
                            public void onResult(UserStateDetails result) {
                                Log.d(TAG, "showSignIn() onResult() result: userState: " + result.getUserState());
                                switch (result.getUserState()) {
                                    case SIGNED_IN:
                                        Log.d(TAG, "showSignIn() callback: SIGNED_IN logged in!");
                                        initializeAndLoadData();
                                        break;
                                    case SIGNED_OUT:
                                        Log.d(TAG, "showSignIn() callback onResult: SIGNED_OUT ");
                                        break;
                                    case SIGNED_OUT_FEDERATED_TOKENS_INVALID:
                                        Log.d(TAG, "showSignIn() callback onResult: SIGNED_OUT_FEDERATED_TOKENS_INVALID");
                                        break;
                                    case SIGNED_OUT_USER_POOLS_TOKENS_INVALID:
                                        Log.d(TAG, "showSignIn() callback onResult: SIGNED_OUT_USER_POOLS_TOKENS_INVALID");
                                        break;
                                    case GUEST:
                                        Log.d(TAG, "showSignIn() callback onResult: GUEST");
                                        break;
                                    case UNKNOWN:
                                        Log.d(TAG, "showSignIn() callback onResult: UNKNOWN");
                                        break;
                                    default:
                                        Log.d(TAG, "showSignIn() callback onResult: default; Should not be possible.");
                                        break;
                                }
                            }

I hope this helps as you wait for an official response from the AWS team.

@tvanmanh
Copy link
Author

@BillBunting Thanks a lot for your help.

@devxpy
Copy link

devxpy commented Apr 17, 2019

@BillBunting Thanks!

It's worth noting that the initialize() function returns the user state as SIGNED_IN even though getCurrentUserState() returns SIGNED_OUT_USER_POOLS_TOKENS_INVALID!

So make sure to call getCurrentUserState().


EDIT: If anyone using flutter came over here, the flutter_cognito_plugin has integrated the workaround for this inside the initialize() function. You just need to upgrade to 0.0.9, and you should be good to go!

devxpy added a commit to scientifichackers/flutter_cognito_plugin that referenced this issue Apr 17, 2019
issue a workaround for aws-amplify/aws-sdk-android#873

minor bug-fixes with exception serializer

use proper callback for getUserAttributes() (in kotlin)
@desokroshan desokroshan added the bug Something isn't working label Aug 13, 2019
@desokroshan desokroshan self-assigned this Aug 13, 2019
@JesusMartinAlonso
Copy link

I'm facing a similar issue
Here are my steps to reproduce it:

1.- Initialize AWSMobileClient

 AWSMobileClient.getInstance().initialize(this, object:Callback<UserStateDetails> {
            override fun onResult(result: UserStateDetails?) {
                //Timber.d("Initialize AWSMobileClient, User State: ${result?.userState}")
            }

            override fun onError(exception: Exception?) {
               // Timber.e(exception, "Error Initialization AWSMobileClient")
            }
        })

2.- Sign in users using hosted UI:

 AWSMobileClient.getInstance().showSignIn(this, signInUIOptions, object : Callback<UserStateDetails> {
                override fun onResult(details: UserStateDetails) {
                    Log.d("TEST", "onResult: " + details.userState)
                }
                override fun onError(e: Exception) {
                    Log.e("TEST", "onError: ", e)
                }
            })

3.- After a successfull sign in, close the app

3.- Open the app again

AWSMobileClient.getInstance().initialize() says that the userState is SIGNED_IN, but fails to retrieve the tokens:

Tokens are invalid, please sign-in again.
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.amazonaws.mobileconnectors.cognitoauth.Auth.setAuthHandler(com.amazonaws.mobileconnectors.cognitoauth.handlers.AuthHandler)' on a null object reference
        at com.amazonaws.mobile.client.AWSMobileClient._getHostedUITokens(AWSMobileClient.java:1645)
        at com.amazonaws.mobile.client.AWSMobileClient.access$900(AWSMobileClient.java:163)
        at com.amazonaws.mobile.client.AWSMobileClient$9.run(AWSMobileClient.java:1576)
        at com.amazonaws.mobile.client.internal.InternalCallback.await(InternalCallback.java:115)
        at com.amazonaws.mobile.client.AWSMobileClient.getTokens(AWSMobileClient.java:1550)
        at com.amazonaws.mobile.client.AWSMobileClient.getUserStateDetails(AWSMobileClient.java:1028)
        at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:828)
        at com.amazonaws.mobile.client.AWSMobileClient$5.run(AWSMobileClient.java:825)
        at com.amazonaws.mobile.client.internal.ReturningRunnable.await(ReturningRunnable.java:31)
        at com.amazonaws.mobile.client.AWSMobileClient.currentUserState(AWSMobileClient.java:807)
        at es.aiwin.games.migo.presentation.initial.InitialActivity.onResume(InitialActivity.kt:78)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1355)
        at android.app.Activity.performResume(Activity.java:7117)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

I have debugged the SDK and the issue is that hostedUI property of AWSMobileClient instance is null. So calling private void _getHostedUITokens(final Callback<Tokens> callback) throws a null pointer exception. It seems that hostedUI is only initialized when showSignIn method is called. This explain why the first time the SDK works fine (showSignIn called to sign in the user) , and why fails when opening the app again (showSignIn not called because the user is already signed in).

I have looked another issues,and this #888 appears to be the same.

It's a very serious bug, that has not been resolved in a long time, so I think that should be resolved as soon as posible. (In my case, our company can not implement SAML login without this issue solved)

@desokroshan
Copy link
Contributor

@JesusMartinAlonso Thanks for reporting the error. I will take a look at it and get back to you. r

@mutablealligator
Copy link
Contributor

I am working on this issue and will have an update when the fix is released. Thank you for the patience.

@mutablealligator
Copy link
Contributor

The HostedUI (CognitoAuth) object has a lifecycle that starts from showSignIn and ends at signOut. However when getTokens() is called after initialize, the hostedUI object is null.

There are two objects for hostedUI (one through awsconfiguration.json and other through code). The AWSMobileClient.initialize always constructs hostedUI through awsconfiguration.json and does not construct the hostedUi object through code.

We are looking into a fix where we could construct one object for hostedUI during initialize which reads off the awsconfiguration.json and is useful for getTokens to work. When showSignIn is called, the same hostedUI object will be mutated to work for a signIn operation. The signOut method should not deallocate the hostedUI object.

I am working on the fix and testing for HostedUI through AWSMobileClient.

@palpatim palpatim added the pending-release Code has been merged but pending release label Aug 23, 2019
@palpatim
Copy link
Member

This has been merged and will go into our next release.

@desokroshan
Copy link
Contributor

A fix has been released in version 2.15.2 of the SDK. Please upgrade and verify.

@desokroshan desokroshan added pending-community-response Issue is pending response from the issue requestor closing soon Issue will auto-close if there is no additional activity within 7 days. and removed pending-release Code has been merged but pending release labels Aug 28, 2019
@stale
Copy link

stale bot commented Sep 4, 2019

This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.

@stale stale bot closed this as completed Sep 4, 2019
@rbarbish
Copy link

rbarbish commented Sep 26, 2019

Still seeing this on 2.15.2, on initialize it will tell me a user is signed in "result.getUserState().equals(UserState.SIGNED_IN)", then later on when I try to getTokens() it will say "AWSMobileClient: waitForSignIn: userState:SIGNED_OUT_USER_POOLS_TOKENS_INVALID in the console".

Also tested on 2.16.0, immediately after it tells me UserState.SIGNED_IN it fails on getTokens() with "SIGNED_OUT_USER_POOLS_TOKENS_INVALID". Makes no sense whatsoever.

@happydroid11
Copy link

Getting the same issue as @rbarbish

@mrinalTASKER
Copy link

Getting the same issues @desokroshan for 2.15.2

@camtittle
Copy link

Getting this in 2.16.2 same as @rbarbish. I'm not using HostedUI but calling signIn manually. Both initialize and getUserState() return SIGNED_IN, but a call to getTokens() immediately afterwards throws an exception: "Tokens are invalid, please sign-in again."

@TobiS97
Copy link

TobiS97 commented Feb 7, 2020

I also get the same error as @rbarbish. I am using the newest version (2.16.+).
Any news about the issue?

@RafaRuiz
Copy link

RafaRuiz commented Jul 6, 2020

News here?

@Tatsato3
Copy link

Any update here?

@ravikanthvob
Copy link

@awsmobilesdk any update pls?. this is making us put an unneccesary long solution in code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working closing soon Issue will auto-close if there is no additional activity within 7 days. mobile client Issues with AWS Mobile's client-side Cognito wrapper pending-community-response Issue is pending response from the issue requestor
Projects
None yet
Development

No branches or pull requests