Aws-sdk-android: "user cancelled" exception

Created on 5 Apr 2019  路  71Comments  路  Source: aws-amplify/aws-sdk-android

Describe the bug:

I followed manual setup to Use Amazon Cognito Hosted UI to implement social login. But I got an error "user cancelled".
when I sign out with API AWSMobileClient.getInstance().SignOut() and then I use your API AWSMobileClient.getInstance().showSignIn(..) to Sign in.
For the first time calls API : it went to facebook/google custom tab (my account signed in facebook/google), it comes back with an error "user cancel" even though i don't close or cancel the chrome. I try to check user state when error"user cancel" by AWSMobileClient.getInstance().addUserStateListener(...): the user state i got is "SIGNED_IN"
But the second times i call that API again it succeeded.
I realized that the "user cancelled" exception is not only thrown when a user closes/cancels the Chrome tab, but also when the tab becomes hidden after successful authentication.

I solved that problem by the way that i use API AWSMobileClient.getInstance().addUserStateListener(...) although it got an error "user cancel" but if the user state is "SIGNED_IN" i will ignore it error. But problem i got here The UI is jerky.

To Reproduce:

** code to sign in **
// For Google
HostedUIOptions hostedUIOptions = HostedUIOptions.builder()
    .scopes("openid", "email")
    .identityProvider("Google")
    .build();

// For Facebook
HostedUIOptions hostedUIOptions = HostedUIOptions.builder()
    .scopes("openid", "email")
    .identityProvider("Facebook")
    .build();

SignInUIOptions signInUIOptions = SignInUIOptions.builder()
    .hostedUIOptions(hostedUIOptions)
    .build();
// 'this' refers to the current active Activity
AWSMobileClient.getInstance().showSignIn(this, signInUIOptions, new Callback<UserStateDetails>() {
    @Override
    public void onResult(UserStateDetails details) {
        Log.d(TAG, "onResult: " + details.getUserState());
    }

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

Environment Information (please complete the following information):

  • AWS Android SDK Version: I tried: 2.12.5, 2.12.7, 2.13.0
  • Device: real device: Samsung, Redmi, Xiaomi
  • Android Version: 7.1.1, 8.1.0

I hope you will fix the problem soon.
Thanks

AWSMobileClient Cognito

Most helpful comment

Come on guys, this is a very heavy issue and nobody provided a proper fix in months... honestly using Cognito is a headache.

Temporary I am patching this by manually re-triggering the Sign In when I get an AuthNavigationException and the message is "user cancelled" (just for the first time).

All 71 comments

Hi,

Please see if SDK release 2.13.2 fixes this issue for you. We have added the following bug fixes:

Fixed erroneous user cancelled error when redirecting back to app.

You may see all changes in the changelog

Hi @minbi
I updated SDK to 2.13.2. The error still occurs.
here is my log:

2019-04-16 09:59:52.820 31442-31629/com.abc.abc D/AWSMobileClient: _federatedSignIn: Putting provider and token in store
2019-04-16 09:59:52.934 31442-31630/com.abc.abc D/AWSMobileClient: Inspecting user state details
2019-04-16 09:59:52.935 31442-31630/com.abc.abc D/AWSMobileClient: hasFederatedToken: true provider: cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_jdpJHzFG6
2019-04-16 09:59:52.935 31442-31630/com.abc.abc D/AWSMobileClient: onResult: Federation from the Hosted UI succeeded
2019-04-16 09:59:52.948 31442-31631/com.abc.abc D/AWSMobileClient: Inspecting user state details
2019-04-16 09:59:53.073 31442-31631/com.abc.abc D/AWSMobileClient: hasFederatedToken: true provider: cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_jdpJHzFG6
2019-04-16 09:59:53.074 31442-31631/com.abc.abc D/ActSocialLogin: onResult: SIGNED_IN
2019-04-16 09:59:54.990 31442-31442/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 09:59:54.992 31442-31442/com.abc.abc D/CognitoCachingCredentialsProvider: Identity id is changed
2019-04-16 09:59:54.992 31442-31442/com.abc.abc D/CognitoCachingCredentialsProvider: Saving identity id to SharedPreferences
2019-04-16 09:59:54.993 31442-31442/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 09:59:54.995 31442-31442/com.abc.abc D/IdentityManager: Signing out...
2019-04-16 09:59:55.021 31442-31442/com.abc.abc D/AWSMobileClient: Inspecting user state details
2019-04-16 09:59:58.968 31442-31634/com.abc.abc I/AWSKeyValueStore: Detected Android API Level = 26
2019-04-16 09:59:58.969 31442-31634/com.abc.abc I/AWSKeyValueStore: Using keyAlias = CognitoIdentityProviderCache.aesKeyStoreAlias
2019-04-16 09:59:58.974 31442-31634/com.abc.abc I/AWSKeyValueStore: Creating the AWSKeyValueStore with key for sharedPreferences = CognitoIdentityProviderCache
2019-04-16 10:00:00.745 31442-31510/com.abc.abc I/AuthClient: customTab hidden callback, code has already been received: false
2019-04-16 10:00:00.748 31442-31668/com.abc.abc E/ActSocialLogin: onError:
    com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
        at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
        at android.support.customtabs.CustomTabsClient$2.onNavigationEvent(CustomTabsClient.java:189)
        at android.support.customtabs.ICustomTabsCallback$Stub.onTransact(ICustomTabsCallback.java:61)
        at android.os.Binder.execTransact(Binder.java:674)
2019-04-16 10:00:00.885 31442-31447/com.abc.abc I/zygote: Do full code cache collection, code=88KB, data=113KB
2019-04-16 10:00:00.886 31442-31447/com.abc.abc I/zygote: After code cache collection, code=82KB, data=77KB
2019-04-16 10:00:01.314 31442-31442/com.abc.abc D/AWSMobileClient: onSuccess: HostedUI signed-in
2019-04-16 10:00:01.322 31442-31442/com.abc.abc D/AWSMobileClient: _federatedSignIn: Putting provider and token in store
2019-04-16 10:00:01.346 31442-31694/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.368 31442-31694/com.abc.abc D/CognitoCachingCredentialsProvider: Identity id is changed
2019-04-16 10:00:01.368 31442-31694/com.abc.abc D/CognitoCachingCredentialsProvider: Saving identity id to SharedPreferences
2019-04-16 10:00:01.374 31442-31696/com.abc.abc D/AWSMobileClient: Inspecting user state details
2019-04-16 10:00:01.375 31442-31694/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.383 31442-31694/com.abc.abc I/chatty: uid=10541(u0_a541) Thread-17 identical 1 line
2019-04-16 10:00:01.401 31442-31694/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.450 31442-31696/com.abc.abc D/AWSMobileClient: hasFederatedToken: false provider: cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_jdpJHzFG6
2019-04-16 10:00:01.450 31442-31696/com.abc.abc D/AWSMobileClient: hasFederatedToken: false provider: cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_jdpJHzFG6
2019-04-16 10:00:01.455 31442-31694/com.abc.abc D/AWSMobileClient: Inspecting user state details
2019-04-16 10:00:01.455 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.456 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.591 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Identity id is changed
2019-04-16 10:00:01.591 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Saving identity id to SharedPreferences
2019-04-16 10:00:01.600 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Clearing credentials from SharedPreferences
2019-04-16 10:00:01.729 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Saving credentials to SharedPreferences
2019-04-16 10:00:01.760 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Saving identity id to SharedPreferences
2019-04-16 10:00:01.870 31442-31696/com.abc.abc D/CognitoCachingCredentialsProvider: Saving credentials to SharedPreferences
2019-04-16 10:00:01.910 31442-31694/com.abc.abc D/AWSMobileClient: hasFederatedToken: true provider: cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_jdpJHzFG6
2019-04-16 10:00:01.910 31442-31696/com.abc.abc W/InternalCallback: Library attempted to call user callback twice, expected only once
2019-04-16 10:00:01.910 31442-31694/com.abc.abc D/AWSMobileClient: onResult: Federation from the Hosted UI succeeded

I am still getting the same issue with latest AWS SDK
along with that at the time of sing out its throwing below exception
" Access Token does not have required scopes "
If anyone got the solution kindly please help me out
Thank You

Hi, I am also getting this exception due to which my success block doesn't execute. I am willing to ignore this error but how i will get the session object then?

Please help me, i creating flugin flutter with hostedUIAws and getting problem :( please tell me why?
LOGIN: onError:
com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
at androidx.browser.customtabs.CustomTabsClient$2$1.run(CustomTabsClient.java:200)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

when i test in android app, it working, but also getting error user cancelled although getting state SIGN_IN

Any news ?
I have same problem.
When i try to login after a signout it return's user canceled exception without showing google signin page. but login was successfull.

@kvasukib any updates on this? We also still see this issue in our app with the latest version of the SDK

I also get the error user cancelled and I don't know what I am doing wrong. Can somebody have a look at this: https://stackoverflow.com/questions/59882918/aws-cognitoauth-user-cancelled-exception-using-aws-hosted-ui ?

Any update on this? We are using 2.16.3 version. When user login with google first time always get error "user cancelled" exception but user state is "SIGN_IN".

I am having the same problem.

this is what I am experiencing.

If you install the app on a new device (it needs to be a new device uninstalling the app or clearing storage/cache does not work) it will work. the App will launch a custom webpage you choose an account and it works with no errors.
if you try again on the same device ( even after clearing storage or new install) tapping the login button will launch a custom webpage but before it finishes loading it will kick you back to the app (before choosing an account from the list) with the error :

2020-02-14 16:09:36.883 30971-30971/com.inkerz.ipsa I/AuthClient: customTab hidden callback, code has already been received: false
2020-02-14 16:09:36.896 30971-31141/com.inkerz.ipsa E/LoginDataSource: onError: 
    com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
        at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
        at androidx.browser.customtabs.CustomTabsClient$2$1.run(CustomTabsClient.java:200)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6702)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)

after that tapp the button again multiple times it will not launch a custom webpage but it will SignIn with the same account you used for the first install/signIn (even though the costum webpage did not launch and you did not choose an account).

I believe the problem is in android.support.customtabs.CustomTabsClient; it might need to be cleared each time we use UIhot sign in

  /**
     * Callback for Custom Tabs to track navigation.
     */
    private final CustomTabsCallback customTabsCallback = new CustomTabsCallback() {
        @Override
        public void onNavigationEvent(final int navigationEvent, final Bundle extras) {
            super.onNavigationEvent(navigationEvent, extras);
            if (navigationEvent == ClientConstants.CHROME_NAVIGATION_CANCELLED) {
                final boolean hasReceivedRedirect = LocalDataManager.hasReceivedRedirect(pool.awsKeyValueStore,
                        context, pool.getAppId());
                Log.i("AuthClient", "customTab hidden callback, code has already been received: " + hasReceivedRedirect);
                if (!hasReceivedRedirect) {
                    userHandler.onFailure(new AuthNavigationException("user cancelled"));
                    LocalDataManager.cacheHasReceivedRedirect(pool.awsKeyValueStore, context, pool.getAppId(), false);
                }
            }
        }
    };
}

this is my UIhost sign In function:

    public Result<LoggedInUser> uiHostGoogleLogIn( Activity callingActivity ,Context context){


        Log.d(TAG, "uiHostGoogleLogIn");


        HostedUIOptions hostedUIOptions = HostedUIOptions.builder()
                .scopes("openid", "email","profile")
                .identityProvider("Google")
                .build();


        SignInUIOptions signInUIOptions = SignInUIOptions.builder()

                .hostedUIOptions(hostedUIOptions)
                .build();




                AWSMobileClient.getInstance().showSignIn(callingActivity, signInUIOptions, new Callback<UserStateDetails>() {



                    @Override
                    public void onResult(UserStateDetails details) {
                        Log.d(TAG, "onResult");

                        Log.d(TAG, "onResult: " + details.getUserState());
                        Log.d(TAG, "onResult: " + details.getDetails());


                    }

                    @Override
                    public void onError(Exception e) {
     Log.e(TAG, "onError: ", e);

                    }
                });


        return isUserLoggedIn(context);

    }

Version implementation('com.amazonaws:aws-android-sdk-cognitoauth:2.15.+@aar') { transitive=true }

Edit:

clearing chrome cache and storage for each signIn fix the problem but is not a usable solution.

Come on guys, this is a very heavy issue and nobody provided a proper fix in months... honestly using Cognito is a headache.

Temporary I am patching this by manually re-triggering the Sign In when I get an AuthNavigationException and the message is "user cancelled" (just for the first time).

Come on guys, this is a very heavy issue and nobody provided a proper fix in months... honestly using Cognito is a headache.

Temporary I am patching this by manually re-triggering the Sign In when I get an AuthNavigationException and the message is "user cancelled" (just for the first time).

I am almost doing the same thing (triggering is the user logged in) AWSMobileClient.getInstance().initialize(

after five seconds from the login.

the problem with this solution is that the user cannot choose from multiple google account and always will be logged in with the cached account.

I think the problem is chrome cache of the login URL if the amplify team could just make each URL unique. I tried adding a dummy parameter with random value using: signInQueryParameters

  HostedUIOptions hostedUIOptions = HostedUIOptions.builder()
                .scopes("openid", "email","profile")
               .signInQueryParameters(test)
                .identityProvider("Google")
                .build();

but it did not work i do not think it added anything to the log in URL.

Any updates on this issue? We are using version 2.16.7 and is still happening

Still no update on the issue,

@minbi mate a lot of people are stuck with this, can we please have a fix or a work around?

@raphkim can we get any update on the status of this bug? This is a serious UX issue with Android, and it calls into question why we chose to go with AWS Cognito in the first place. I see that many developers like @kvasukib and @minbi attempted to fix it but didn't find success, however it now looks like it has been abandoned or something.

Please give us some assurance that someone understands the severity of this issue and that attention is given to developers' feedback.

Hi,

Thank you for bringing this to our attention and I apologize for the delayed response. I will raise this issue with the team today and give an update as soon as possible.

Thank you.

I found a workaround that prevents the Error ( at least for me) and kinda satisfy my requirements.
hopefully, it can help whoever stuck on this issue until a proper solution is ready.

logout the user from the app and the browser before login again.

you can do that by both using the normal signout and also opening the logout URL in the browser.

 val AWS_OAuth_Logout_URL = "https://"+ AWS_OAuth_WebDomain + "logout?client_id="+ AWS_OAuth_AppClientId +"&response_type=code&scope=email+openid+profile&logout_uri="+AWS_OAuth_SignOutRedirectURI

        AWSMobileClient.getInstance().signOut();

        val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(AWS_OAuth_Logout_URL))
        startActivity(context,browserIntent,null)

Using chrome custom tab make a little bit cleaner UI/UX experience.

Quick note to let ya know that I'm able to reproduce it here and actively working on it.

@m-aljammali-inkerz thanks for posting the workaround - I'll look into that and see if it helps point to a permanent fix!

Found the issue for the user cancelled exception - it's a race condition between the customTab being closed callback method and the deep link method being called from HostedUI after sign in occurs. I'll work on fixing this now.

Not being able to see the HostedUI sign in interface to select a different account after logging out is a separate issue we'll address after.

Hey all, sorry for the delay on this - in investigating I'm coming across another apparent race condition where it seems the customTab navigation listener doesn't always get attached.

Has anyone encountered an issue (particularly with a new project) where when you cancel out of the web view, it doesn't give the correct "user cancelled" error callback?

@TrekSoft any updates?
Thanks

Still definitely on my radar - had to take a pause for another more urgent issue and also we're pretty heads down preparing Amplify Android for GA but hope to return to work on this Friday. Will keep you posted here.

I found a fix for this, which is not related to the library, but you guys have to change the documentation https://aws-amplify.github.io/docs/sdk/android/authentication

Make sure that the activity where you're logging has a single instance launch mode. Because otherwise there will be another activity created on top.

 <activity
            android:name="com.dtl.kaloric.ui.auth.AuthActivity"
            android:launchMode="singleInstance">

And don't override onResume, but override onNewIntent

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        AWSMobileClient.getInstance().handleAuthResponse(intent)
    }

Doing this, will make the login work first time.

This is amazing @boldijar - thanks for posting - I'd dedicated today to this issue so I'll try out that solution here as part of it.

Alright so I tried it out here and it does indeed work beautifully as well as preventing the other issue of the onCreate method of your activity getting called again (multiple times) after successfully signing in. In addition to being unexpected and sometimes fatal behavior, that was the root cause of the app flashing white after signing in.

So here's the proposed solution which I'd love to get feedback on and depending on how it goes, and what the team suggests, will update the documentation to reflect this.

Suggested Solution To The User Cancelled Issue

In your AndroidManifest.xml file, add the following property to whichever activity will be launching HostedUI: android:launchMode="singleInstance"

e.g.

<application>
   <activity 
        android:name=".MainActivity" 
        android:launchMode="singleInstance">
   </activity>
</application>

Also, instead of the onResume method currently specified in the documentation, use this method instead (where "myapp" is whatever scheme you set for the callback link per the documentation) :

   @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if(intent.getData() != null &&
                "myapp".equals(intent.getData().getScheme())) {
            AWSMobileClient.getInstance().handleAuthResponse(intent);
        }
    }

Caveat: It's important to note that setting the launch mode to singleInstance can change how navigation back to that activity works. If you go from activity A -> B -> C where B is the singleInstance activity, the navigation order pressing the Back button will be from C -> A -> B.

This article does a nice job describing what exactly happens when you set the activity mode to single instance and this StackOverflow question directly addresses why navigation works that way. However, I imagine most of you wouldn't support navigating back before the activity which launches HostedUI after a successful sign in anyway so this may not be a significant issue.

I tried it quickly it did not work for me.
I will try again when I have time but if there is more info I appreciated it

I can confirm this workaround fixed our issue and now our Hosted UI is working perfectly fine without this glitch.

@m-aljammali-inkerz - no more info at this time - let us know when you've been able to thoroughly test it and if it's still not working, if you could post your code snippet and what error you're getting that'd be good.

Is it working on emulator as well?
I fixed my code as suggested but seems not working well on emulator.

UPDATED: Never mind! It was my fault. It works well!

AWS SDK version: 2.16.12
Problem is still reproduced.

 var buggedUserStateDetails: UserStateDetails? = null
            try {
                buggedUserStateDetails = awsClient.showSignIn(
                    (context as MyApplication).currentActivity,
                    signInUIOptions
                )
            } catch (e: Exception) {
                //**Here is AuthNavigationException: user cancelled**
                Timber.e(e)
            }

workaround with
android:launchMode="singleInstance"
and onNewIntent(Intent intent)
doesn't help because Exeption throws before method onNewIntent fires

@igorka48 can you post the section of your AndroidManifest.xml where you added that launch mode? Did you add it to the activity which is making the call to launch hosted UI?

 <activity
                android:name=".ui.auth.facebook.activity.FacebookLoginActivity"
                android:configChanges="keyboardHidden|orientation"
                android:screenOrientation="fullUser"
                android:launchMode="singleInstance"
                android:theme="@style/AppTheme.TranslucentStatusBar"
                android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="myapp" />
            </intent-filter>
        </activity>

Ok, and so it's in your FacebookLoginActivity file where you are launching HostedUI?

To test if you have singleInstance launch mode applying correctly, you can try navigating from a page before that Activity to a page after it and then doing a back navigation action. If it takes you to FacebookLoginActivity, you don't have it setup correctly. It should take you back to the page you were on before FacebookLoginActivity.

Just wanted to confirm that I'm also seeing this issue with version 2.16.12

The android:launchMode="singleInstance" workaround is not working.

I also suspect it's a chrome cache issue. The custom chrome tab launches but immediately closes, "user cancelled" exception is thrown, but then I'm logged in with the last account I chose in the Google account chooser.

To reproduce use hosted ui to social sign in with Google. Sign out. Use hosted ui to social sign in with Google again.

        HostedUIOptions hostedUIOptions = HostedUIOptions.builder()
                .identityProvider("Google")
                .disableFederation(true)
                .build();

        SignInUIOptions signInUIOptions = SignInUIOptions.builder()
                .hostedUIOptions(hostedUIOptions)
                .build();

        awsMobileClient.showSignIn(activity, signInUIOptions, new Callback<UserStateDetails>() {
            @Override
            public void onResult(UserStateDetails result) {
                callback.onSuccess();
            }

            @Override
            public void onError(Exception e) {
                callback.onFailure(e.getLocalizedMessage());
            }
        });
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
             awsMobileClient.handleAuthResponse(intent);
        }
    }

@RecargoJereld - could you post the snippet of your AndroidManifest where you added android:launchMode="singleInstance"? Also could you confirm the name of the activity those code snippets you posted above are from?

Note that this workaround does not address the issue of not being able to choose a different account. That's still an issue I plan to look into.

I am running into this issue even with the suggested fix. Below are the details of my setup and repro steps. Let me know if you need more information:

Cognito abstraction class:

public class CognitoAuthEndpoint {
    private Auth cognitoAuth;

    CognitoAuthEndpoint(Context context) {
        this.cognitoAuth = new Auth.Builder()
                .setApplicationContext(context.getApplicationContext())
                .setAppClientId(context.getString(R.string.cognito_user_client_id))
                .setAppCognitoWebDomain(context.getString(R.string.cognito_web_domain))
                .setSignInRedirect(context.getString(R.string.cognito_app_redirect))
                .setSignOutRedirect(context.getString(R.string.cognito_app_redirect))
                .setAuthHandler(new AuthCallback())
                .build();
    }

    public void loginUser(
            Response.Listener<String> listener,
            Response.ErrorListener errorListener) {
        this.getSessionListener = listener;
        this.authErrorListener = errorListener;
        cognitoAuth.getSession(true);
    }

    class AuthCallback implements AuthHandler {

        @Override
        public void onSuccess(AuthUserSession authUserSession) {
            Log.d(LOG_TAG, "Login success");
            cognitoUserSession = authUserSession;

            if (getSessionListener != null) {
                getSessionListener.onResponse(getTokenFromSession());
            }
        }

        @Override
        public void onSignout() {
            Log.d(LOG_TAG, "User signed out");

            if (logoutListener != null) {
                logoutListener.onResponse(null);
            }
        }

        @Override
        public void onFailure(Exception exception) {
            Log.e(LOG_TAG, "Failed to auth", exception);
            sharedAuthErrorHandler(exception, authErrorListener);
        }
    }
}

Activity which invokes hosted UI and receives the response

public class AuthenticationActivity extends AppCompatActivity {
    private AuthEndpoint authEndpoint;
    private Uri authRedirectUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_authentication);

        authEndpoint = //...
        authRedirectUri = Uri.parse(getString(R.string.cognito_app_redirect));
    }

    @Override
    protected void onResume() {
        super.onResume();

        Intent authCallbackIntent = getIntent();
        if (authCallbackIntent.getData() != null &&
                authRedirectUri.getHost() != null &&
                authRedirectUri.getHost().equals(authCallbackIntent.getData().getHost())) {
            authEndpoint.processCallbackIntentData(authCallbackIntent.getData());
        }
    }

    @OnClick(R.id.login_btn)
    public void handleLoginClick() {
        authEndpoint.loginUser(
                response -> {
                    Log.i(LOG_TAG, "Sign in successful, auth sequence completed.");
                },
                error -> {
                    Log.e(LOG_TAG, "Error in sign in, try logging in again.", error);
                }
        );
    }
}

Repro Steps:

  1. Press login button
  2. Chrome tab opens up, then closes
  3. Logs indicate that the user cancelled error was received and then the sign in succeeded:
E/CognitoAuthEndpoint: Failed to auth
    com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
        at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
        at androidx.browser.customtabs.CustomTabsClient$2$1.run(CustomTabsClient.java:200)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
....
....
D/CognitoAuthEndpoint: Login success

Now I made the following changes:

AndroidManifest.xml

<activity
            android:name=".ui.screens.AuthenticationActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="www.demo.com"
                    android:path="/signin"
                    android:scheme="demo" />
            </intent-filter>
        </activity>

AuthenticationActivity

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        Intent authCallbackIntent = getIntent();
        if (authCallbackIntent.getData() != null &&
                authRedirectUri.getHost() != null &&
                authRedirectUri.getHost().equals(authCallbackIntent.getData().getHost())) {
            authEndpoint.processCallbackIntentData(authCallbackIntent.getData());
        }
    }

Repro steps:

  1. Press login button
  2. Chrome tab opens, then closes
  3. Logs indicate that the user cancelled error was received
  4. IMPORTANTLY. The sign in succeeded callback was not received
E/CognitoAuthEndpoint: Failed to auth
    com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
        at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
        at androidx.browser.customtabs.CustomTabsClient$2$1.run(CustomTabsClient.java:200)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

Can you remove the onResume method from AuthenticationActivity?

I did. Replaced onResume with onNewIntent in the second attempt described above.

Ah gotcha - could you add a log statement to the onNewIntent method just to be sure it's coming in through there?

I have the same problem as @abhineet255 the onNewIntent is not reached.

I also had another problem using 2 factor authentication. The chrometab was being closed when I received a phone call to enter the code. So I applied the fix below to make sure the tab remained open. Could this fix be the reason the onNewIntent is not reached?

Replaced:
mCustomTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); mCustomTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
With
mCustomTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

Thanks for that update @tlambeir - my understanding is that @abhineet255 is reaching the onNewIntent method but is still getting the user cancelled error. If you're not reaching your onNewIntent method, you may have a problem in how you setup the manifest XML. Can you verify the name of the Activity you launch HostedUI from and the corresponding snippet of the manifest where you updated that activity to have a singleInstance launch mode.

Also @abhineet255 I just realized that the issue is you're not using AWSMobileClient but the low level SDKs. In AWSMobileClient we have special code to handle the fact that the Chrome tab closing callback needs to know whether the internal callback URI got triggered in order to know whether it was a cancel or a successful sign in.

If you want to use the low level client you'd have to rewrite that code yourself.

@m-aljammali-inkerz and anyone else who were reporting the side issue of the fact that when you sign in with Hosted UI, sign out, and then try signing in again you can't select an account, the solution is to sign out with the invalidateTokens option set to true per the docs here: https://docs.amplify.aws/sdk/auth/hosted-ui/q/platform/android#sign-out-from-hostedui-1

@TrekSoft Thanks for looking into this. I am reaching onNewIntent when I'm not using 2 factor authentication and the activity is set to single instance in the manifest.

It's only when the app gets put into the background because I receive a phone call from the 2 factor authentication that it doesn't. I think the custom tab can not handle a deep link when the activity is pauzed?

Aha - thanks for that clarification. We're tracking that bug with MFA here and have it on our roadmap to address soon: https://github.com/aws-amplify/aws-sdk-android/issues/764

Since it's been a couple months since posting the solution and it seems to be working, we updated the documentation to use that and will be closing this ticket. If you have additional issues with it, feel free to post it here but will leave this closed unless we have a confirmed case where everything was setup correctly with AWSMobileClient and it still didn't work.

@TrekSoft I am getting the same signin with web UI failed error, while trying to login 1st time after logout.

This my manifest,

<activity
android:name=".ui.login.AuthActivity"
android:launchMode="singleInstance">

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="myapp" />
</intent-filter>
</activity>

I am calling below function on button click of fragment resided in AuthActivity.

activity?.let {
Amplify.Auth.signInWithSocialWebUI(
AuthProvider.facebook(),
it,
{ result ->
signUpViewModel.handleSocialSignUpResponse(result)
},
{ error ->
signUpViewModel.handleSocialSignUpError(error)
}
)
}

This is onNewIntent() of AuthActivity

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent?.data != null && "myapp" == intent.scheme) {
Amplify.Auth.handleWebUISignInResponse(intent)
// AWSMobileClient.getInstance().handleAuthResponse(intent)
}
}

This is how I am signing out.

Amplify.Auth.signOut(AuthSignOutOptions.builder().globalSignOut(true).build(),
{
launchMain {
progressLD.value = false
}
sharedPrefs.put(SharedPrefs.PREF_IS_USER_LOGGED_IN, false)
_logOutLiveData.postValue(Event(app.applicationContext.getString(R.string.logout_successfully)))
},
{ error ->
launchMain {
progressLD.value = false
}

if (error.cause is AmazonServiceException) {
_errorLiveData.postValue(Event((error.cause as AmazonServiceException).errorMessage.orEmpty()))
} else {
_errorLiveData.postValue(Event(error.localizedMessage.orEmpty()))
}
}

Can you put a log statement inside your onNewIntent method and see if the code is ever hitting that?

Also btw, you can make code snippets like the ones you posted above more readable by putting three back-ticks ` before the code and three after like this: https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks

I am having the same problem. The onError callback method fires with AuthNavigationException: user cancelled before onNewIntent gets called. The activity has singleInstance flag set.

Alright we found a complete fix to this issue and will be implementing it soon.

Basically we'll include two activities in the SDK, one which will launch the custom Chrome tab and one which will handle the callback URL and return the response so you don't have to worry about modifying the manifest and setting up the onNewIntent listener like you do now - it will all just work.

@TrekSoft When the new release gonna happen?

We're scheduling this work for this sprint so not sure how long it'll end up taking to complete but will give an update on this ticket when there's new information.

@TrekSoft
Thanks for comment,
I am also facing same issue. Let me give you details regarding SDK version.

AWS Sdk version - 2.16.12
Target SDK : 29

Error Log:

2020-07-24 01:52:43.980 20521-21303/com.oxit.npi V/FA: Activity resumed, time: 2270499836
2020-07-24 01:52:43.996 20521-21303/com.oxit.npi V/FA: Connecting to remote service
2020-07-24 01:52:44.078 20521-21303/com.oxit.npi D/FA: Connected to remote service
2020-07-24 01:52:44.079 20521-21303/com.oxit.npi V/FA: Processing queued up service tasks: 1
2020-07-24 01:52:44.897 20521-20521/com.oxit.npi I/AuthClient: customTab hidden callback, code has already been received: false

2020-07-24 01:45:33.665 19354-19700/com.oxit.npi W/System.err: com.amazonaws.mobileconnectors.cognitoauth.exceptions.AuthNavigationException: user cancelled
2020-07-24 01:45:33.665 19354-19700/com.oxit.npi W/System.err:     at com.amazonaws.mobileconnectors.cognitoauth.AuthClient$4.onNavigationEvent(AuthClient.java:624)
2020-07-24 01:45:33.665 19354-19700/com.oxit.npi W/System.err:     at androidx.browser.customtabs.CustomTabsClient$2$1.run(CustomTabsClient.java:200)
2020-07-24 01:45:33.665 19354-19700/com.oxit.npi W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at android.os.Looper.loop(Looper.java:214)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7397)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
2020-07-24 01:45:33.666 19354-19700/com.oxit.npi W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
2020-07-24 01:45:37.862 19354-19401/com.oxit.npi V/FA: Inactivity, disconnecting from the service

Can you please update on this, As we need to release app on play store asap. :)

@TrekSoft

I have same issue, Same log match with @jigs611989
Can you please help me for this and give update.

@gauravbordoloi Is there any solution you get ?

Still in development queue here - will update the ticket when the fix is implemented.

@TrekSoft This is critical as it is blocking the social login. Can you tell me the workaround for this issue and when do you expect the release for the fix?

The workaround which appears to help most people is here: https://github.com/aws-amplify/aws-sdk-android/issues/871#issuecomment-608547360

However it doesn't solve it for everyone and I'm working on a complete fix this sprint. I expect it to be released in about a month.

@TrekSoft Thanks for providing an update on this last week. Where can track the open ticket for this issue? I see this issue is listed as closed.

I'll reopen it here since it seems the previously mentioned fix isn't working for everyone and will close it once the new fix I'm working on here is released.

Are there any workarounds that work in the interim? #871 (comment) does not work for us. We're planned to launch a major update of our app having switched to AWS and this was one of the last pieces left. Figured social logins are so common place now, there's no way it _wouldn't_ be working for Cognito.... Please, any help at all to at least allow us to sign in some way somehow until its fixed properly would be much appreciated!

Hey @DigitalLeverage as you can see I just put up the PR for this so it should be released at least by next week Thursday. In the meantime, you could use federatedSignIn instead of HostedUI to handle social login: https://docs.amplify.aws/sdk/auth/federated-identities/q/platform/android

Thanks for the quick reply @TrekSoft ! If we use Identity Pools for the time being only for social, is that going to cause an issue when we switch back to using the User Pool once the fix is in?

I'm not 100% sure how that works if you sign in with federatedSignIn with a social account and then later sign in with that same account on HostedUI which will federated it with User Pools. You could test it out and see. In the meantime, I just merged the fix to develop so it'll be going out with the next release either this week or next.

@TrekSoft
I can't say that this issue is fully fixed in 2.18.0.
I upgraded cognito sdk to 2.18.0 and followed this guide to make changes in my code.
Now, in android studio, when i open AndroidManifest.xml and view merged manifest, i see the following activity:

        <activity
            android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="FOR_LIBRARY_CONSUMER_TO_OVERRIDE" />
            </intent-filter>
        </activity>

Please pay attention to this line:
<data android:scheme="FOR_LIBRARY_CONSUMER_TO_OVERRIDE" />

I guess it comes from this build.gradle file

As a workaround i added the following code to my AndroidManifest.xml and now seems like everything is ok.

        <activity
            android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="${authRedirectScheme}" />
            </intent-filter>
        </activity>

@AlexZvonik thanks for the update - I'm seeing that too now. When I had tested it the value in the app build.gradle overruled that one but now it seems it's not doing that. Will investigate.

@TrekSoft
In my build.gradle i have the following block:

android {

    compileSdkVersion build_versions.targetSdk
    buildToolsVersion build_versions.buildTools

    useLibrary 'org.apache.http.legacy'
    flavorDimensions defaultDimension

    defaultConfig {
       ...
        manifestPlaceholders = [
                'authRedirectScheme': 'parentapp'
        ]
       ...
    }

}

But i believe the problem is that FOR_LIBRARY_CONSUMER_TO_OVERRIDE was set when aws-android-sdk-cognitoauth was built on you CI/CD machine.

I tried to create a new project with the only dependencies as shown below + defined manifestPlaceholders in _android_ -> _defaultConfig_ , and i got the same result.

                    implementation "com.amazonaws:aws-android-sdk-core:2.18.0"
                    implementation "com.amazonaws:aws-android-sdk-mobile-client:2.18.0"
                    implementation "com.amazonaws:aws-android-sdk-cognitoauth:2.18.0"

Thanks - yeah looking into it here it seems the solution is the one you came upon yourself of defining the redirect activity from our library in your own manifest so I will be testing this here and updating the documentation accordingly.

Alright, updated the documentation to simply add the activity to your AndroidManifest file with the intent string included instead of using the manifestPlaceholder. Will perform a code cleanup task to remove it from the library manifest and build.gradle but for now, they'll just get overridden: https://docs.amplify.aws/sdk/auth/hosted-ui/q/platform/android#setup-amazon-cognito-hosted-ui-in-android-app

To all following this ticket, this issue is now resolved in version 2.18.0 which introduces a breaking usage change in how to listen for the HostedUI response - see the documentation link above for the small modifications needed to use it.

@TrekSoft I followed the documentation and now I have some issue that is weird - a crash on the .showSignIn method -
Throwing an excetion:

No virtual method getSession()V in class Lcom/amazonaws/mobileconnectors/cognitoauth/Auth; or its super classes (declaration of 'com.amazonaws.mobileconnectors.cognitoauth.Auth'

I am using aws sdk 2.18.0 and 2.19.0 with android sdk 29

I am lost now... Please, can yo suggest something what to try?

Hey jugos,

This sounds like a different issue so can you file a new issue with the following information:

  1. Relevant code snippets of what you're calling
  2. How you configured your project through the CLI
  3. Your gradlew file with your dependencies

Thanks

Thank you @TrekSoft I opened new one:
https://github.com/aws-amplify/aws-sdk-android/issues/2145

Was this page helpful?
0 / 5 - 0 ratings