aws-amplify / aws-sdk-android

AWS SDK for Android. For more information, see our web site:
https://docs.amplify.aws
Other
1.03k stars 551 forks source link

User Id is null when user is signed in #622

Open CriPstian opened 5 years ago

CriPstian commented 5 years ago

Hi there, I need help implementing some basic functionality and can't figure it out with the help of the documentation. Let me know if there is need for more logs or information. Thanks!

Signing in users Using sign in on Android with Facebook or with Google signs in with success but does not provide access to username or any attribute due to userId being null. I want to be able to extract the basic information like username or email to let the user know how they are signed in.

AWS Services Went through amplify example and tutorial step by step, also just by using the android sdk and configuraiton in the AWS Console.

Exceptions After the sign in is completed, the onResult callback will come back with a SIGNED_IN user state (which is awesome).

Build environment

ext {
    kotlin_version = '1.3.11'
    supportlibVersion = '1.1.0-alpha01'
}

dependencies:

//Base SDK
    implementation 'com.amazonaws:aws-android-sdk-core:2.9.0'
    //AppSync SDK
    implementation 'com.amazonaws:aws-android-sdk-appsync:2.6.28'

    //For AWSMobileClient only:
    implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.9.0'

    //For the drop-in UI also:
    implementation 'com.amazonaws:aws-android-sdk-auth-userpools:2.9.0'
    implementation 'com.amazonaws:aws-android-sdk-auth-ui:2.9.0'

    // Facebook SignIn
    implementation('com.amazonaws:aws-android-sdk-auth-facebook:2.8.0')

    // Google SignIn
    implementation('com.amazonaws:aws-android-sdk-auth-google:2.8.0')

Device Information

scb01 commented 5 years ago

@CriPstian

Sorry to hear that you are running into issues. From your description, looks like you are doing everything correctly. Can you post a code snippet? that may help identify why it is not working.

CriPstian commented 5 years ago

@cbommas

I am initializing the AWSMobileClient in my MainActivity.class as suggested, in the onCreate method.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        AWSMobileClient.getInstance().initialize(applicationContext, object : Callback<UserStateDetails> {

            override fun onResult(userStateDetails: UserStateDetails) {
                Log.v("DosNDonts", "GOT RESULT ON INITIALIZE: ${userStateDetails.userState}")
                when(userStateDetails.userState) {
                    UserState.SIGNED_IN -> login.run {
                        text = "LOGGED IN: ${AWSMobileClient.getInstance().username}"
                        setRightCompoundDrawable(R.drawable.ic_user_is_logged_in)
                    }
                    UserState.SIGNED_OUT -> login.run {
                        setText(R.string.not_logged_in)
                        setRightCompoundDrawable(R.drawable.ic_user_is_logged_out)
                    }
                    else -> AWSMobileClient.getInstance().signOut()
                }
                login.isClickable = true
                login.isFocusable = true
                Log.i("INIT", "onResult: " + userStateDetails.userState)
            }

            override fun onError(e: Exception) {
                Log.e("INIT", "Initialization error.", e)
            }
        })
    }

Sorry if this is too much code, but the moment that I get to the onResult method, the userId should be set already. Below I want to show how I am displaying the loginUI:


AWSMobileClient.getInstance().showSignIn(this, object : Callback<UserStateDetails> {
    override fun onResult(result: UserStateDetails) {
        when(result.userState) {
            UserState.SIGNED_IN -> {
                login.text = "LOGGED IN: ${AWSMobileClient.getInstance().username}"
                login.setRightCompoundDrawable(R.drawable.ic_user_is_logged_in)
            }
            UserState.SIGNED_OUT -> {
                login.setText(R.string.not_logged_in)
                login.setRightCompoundDrawable(R.drawable.ic_user_is_logged_out)
            }
            else -> AWSMobileClient.getInstance().signOut()
        }
        login.isClickable = true
        login.isFocusable = true
        Log.i("INIT", "onResult: " + result.userState)
    }

    override fun onError(e: java.lang.Exception?) {
        Log.v("INIT", "ERROR ON LOGIN")
    }
})

One thing that I do not want to do is confirm the user with multi factor authentication, is that a mandatory to do even if I have it disabled on the serverless architecture?

minbi commented 5 years ago

Using sign in on Android with Facebook or with Google signs in with success but does not provide access to username or any attribute due to userId being null.

We do not support retrieving the username when using federatedSignIn with Facebook or Google.

CriPstian commented 5 years ago

Hello @minbi thanks for adding that. I would still need to extract certain attributes from signed in user. This way it would be possible to display the user some confirmation that it was successfully signed in and is able to access his or hers data. In that aspect, the userId, being null, I am not able to access the user attributes.

minbi commented 5 years ago

Federated sign-in for Google and Facebook currently does not return any information other than the AWS credentials and the associated Amazon Cognito identity id. I have marked this issue as a feature request and will have a discussion with our team about whether this can be supported. At this time, you will need to manage/retrieve that information yourself.

BillBunting commented 5 years ago

@CriPstian ,

I wanted to do the same thing, so I could get basic information about a federated user to add to a DynamoDB table.

I collected the sign-in info I needed directly from the federated provider's API. First, I try to determine which federated login was used. Maybe there is a better way via an AWS API.

  public void updateBioFromSignInProvider () {
    Log.d(TAG, "updateBioFromSignInProvider()");

        FacebookSdk.setApplicationId(getString(R.string.facebook_app_id));
        //initialize Facebook SDK
        FacebookSdk.sdkInitialize(getApplicationContext());

        if (AccessToken.getCurrentAccessToken() != null) {
            Log.d(TAG, "updateBioFromSignInProvider(): Facebook sign-in found.");
            (new GetFacebookProfileTask()).execute();
        } else if (GoogleSignIn.getLastSignedInAccount(this) != null) {
            Log.d(TAG, "updateBioFromSignInProvider(): Google sign-in found.");
            (new GetGoogleProfileTask()).execute();
        } else {
            // Most be Cognito User Pool
            if (doShowProfileUpdateRequest) {
                showProfile();
                showUpdateProfileAlert();
            }
        }
    }

For Facebook, I grab the info with a Graph request ... GraphRequest graphRequest = new GraphRequest(AccessToken.getCurrentAccessToken(), "me");

For Google, I call

GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(MainActivity.this);
            String personName = acct.getDisplayName();
            String personGivenName = acct.getGivenName();
            String personFamilyName = acct.getFamilyName();
            String personEmail = acct.getEmail();
            String personId = acct.getId();
            Uri personPhoto = acct.getPhotoUrl();

This has been working okay, but I'd like a more direct approach to find out which federated sign-in was used and return some basic info like their email and profile image URL.

kirillvasilenko commented 3 years ago

Any updates on this issue?