#StackBounty: #amazon-web-services #amazon-cognito #amazon-iam #aws-appsync Switching unauthenticated user to authenticated user

Bounty: 200

I’m trying to set my app up to allow unauthenticated users to access an AppSync API, as mentioned in https://docs.aws.amazon.com/cognito/latest/developerguide/switching-identities.html . Ideally they would be able to start using the app, then sign in and keep all their data.

I’ve got:

  1. A user pool. This is set up for Google auth/regular cognito auth
  2. An identity pool

    This is linked to the user pool via a Cognito identity provider.
    The authenticated/unauthenticated roles have a policy attached to them that gives them access to the GraphQL API

  3. An AppSync API set up with AWS_IAM auth

I create the app sync client like this:

val credentialsProvider = CognitoCachingCredentialsProvider(
    context,
    "us-east-2:abc...etc",
    Regions.US_EAST_2)
appSyncClient = AWSAppSyncClient.builder()
    .context(applicationContext)
    .awsConfiguration(awsConfiguration)
    .credentialsProvider(credentialsProvider)
    .build()

This works fine and the identity pool creates an identity for me, and I can interact with the API. Well, it creates two anonymous identity IDs, but it works. The real trouble comes when I log in:

val hostedUIOptions: HostedUIOptions = HostedUIOptions.builder()
    .scopes("openid", "email", "aws.cognito.signin.user.admin")
    .build()
val signInUIOptions: SignInUIOptions = SignInUIOptions.builder()
    .hostedUIOptions(hostedUIOptions)
    .build()
 
runOnUiThread {
    mobileClient.showSignIn(
        mainActivity,
        signInUIOptions,
        object : Callback<UserStateDetails?> {
            override fun onResult(result: UserStateDetails?) {
                Log.i("AwsAuthSignIn", "onResult: " + result?.userState)
            }
 
            override fun onError(e: Exception?) {
                Log.i("AwsAuthSignIn", "onResult: " + result?.userState)
            }
 
        }
    )
}

After that I see that it’s created a new identity associated with the sign in, rather than use the old one. I thought it was supposed to seamlessly transfer over the old identity ID to be connected with the authenticated user.

I’ve also tried calling registerIdentityChangedListener to see if it fires on logging in, but it does not. It only fires when first getting the unauth identity IDs.

Also when I log into the same account from two different device it creates two different identity IDs for the same user in the user pool. Since I’m using identityId to track RDB record ownership, this means that the same user sees different items after logging in.

So is identityId the right thing to put in the database? Is it expected to be different for different devices? I’m trying to find something else to use but am coming up dry.

This is what’s available in the "identity" section of the context for use with VTL resolvers:

"identity": {
    "accountId": "________",
    "cognitoIdentityAuthProvider": ""cognito-idp.us-east-2.amazonaws.com/us-east-2_______","cognito-idp.us-east-2.amazonaws.com/us-east-2_______:CognitoSignIn:____________"",
    "cognitoIdentityAuthType": "authenticated",
    "cognitoIdentityId": "us-east-2:___",
    "cognitoIdentityPoolId": "us-east-2:___",
    "sourceIp": [
        "_____"
    ],
    "userArn": "arn:aws:sts::_________:assumed-role/amplify-focaltodokotlin-prod-222302-authRole/CognitoIdentityCredentials",
    "username": "__________:CognitoIdentityCredentials"
}

"username" is the only other one that makes sense, but when I call AWSMobileClient.username on my side, it comes up with a different format: "Google_". So I wouldn’t be able to match it up in client-side logic.

Is this possible at all or do I need to abandon the idea of unauthenticated use and go with User Pools directly?


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.