aws / aws-aspnet-cognito-identity-provider

ASP.NET Core Identity Provider for Amazon Cognito
https://aws.amazon.com/developer/language/net/
Apache License 2.0
213 stars 89 forks source link

UserManager.AddToRoleAsync returns an error, but works #191

Closed mrsuau627 closed 3 years ago

mrsuau627 commented 3 years ago

I've been using this library for about 9 months without any issues. Now we're trying to move over to our production environment and we're getting an odd error when calling UserManager.AddToRoleAsync after creating a new user.

Here's the code we're using:

            var newUser = _cognitoUserPool.GetUser(userName);
            // create the user with the following attributes
            newUser.Attributes.Add(CognitoAttribute.Email.AttributeName, email);
            newUser.Attributes.Add(CognitoAttribute.FamilyName.AttributeName, lastName);
            newUser.Attributes.Add(CognitoAttribute.GivenName.AttributeName, firstName);
            newUser.Attributes.Add(CognitoAttribute.PhoneNumber.AttributeName, phoneNumber);
            var result = await _userManager.CreateAsync(newUser, password);
            if (!result.Succeeded)
            {
                // code to handle the returned error(s)
            }
            else
            {
                // add them to the appropriate group/role
                result = await _userManager.AddToRoleAsync(newUser, role.ToString());
                if (!result.Succeeded)
                {
                }
            }

After calling AddToRoleAsync, result.Succeeded == false and result.Errors contains a single error that says: Code = "CognitoServiceError" Description = "Failed to update the Cognito User : 1 validation error detected: Value null at 'userAttributes' failed to satisfy constraint: Member must not be null"

The odd thing is that if I look in Cognito, my user is created successfully AND they are added to the correct Cognito group. Everything functions fine, but I get this error every time. This does not happen in our dev account. It functions correctly there and returns Succeeded = true with no errors.

My question is, do you know what could cause Cognito to report this error in 1 AWS account and not the other?

Environment

This is a :question: general question

ashishdhingra commented 3 years ago

Hi @mrsuau627,

Good morning.

Could you please share the following:

Thanks, Ashish

mrsuau627 commented 3 years ago

Hi @ashishdhingra ,

I'm currently using 1.0.5 of the Amazon.AspNetCore.Identity.Cognito nuget pkg. My first step before creating this issue was to try 2.0.2, but it didn't make a difference. Plus, we have our dev environment still working correctly with 1.0.5.

I've set up another User Pool in our dev environment using the same Terraform script that I used for production and I'm reproducing the same error. Here are the details of that User Pool: general settings

attributes

app client

app client attributes

Let me know if you need anymore info.

Thanks!

ashishdhingra commented 3 years ago

Hi @mrsuau627,

Using the NuGet Package Amazon.AspNetCore.Identity.Cognito version 2.0.2, I tried the following:

  1. Created user pool and app client with the settings you specified.
  2. User Sample solution in this repository and configured the settings in appsettings.Development.json
  3. Ran the Register user flow. The following code is executed:
    
    var user = _pool.GetUser(Input.UserName);
    user.Attributes.Add(CognitoAttribute.Email.AttributeName, Input.Email);
    user.Attributes.Add(CognitoAttribute.FamilyName.AttributeName, lastName);
    user.Attributes.Add(CognitoAttribute.GivenName.AttributeName, firstName);
    user.Attributes.Add(CognitoAttribute.PhoneNumber.AttributeName, phoneNumber);

var result = await _userManager.CreateAsync(user, Input.Password); if (result.Succeeded) { }


**RESULT:** `result.Succeeded` is `false` with the error `Failed to create the Cognito User : A client attempted to write unauthorized attribute`. 

5.  Noticed that the user creation logic is adding attributes Family Name, Given Name and Phone Number. However, these attributes do not have write permissions in app client settings. **Configured the app client settings to add write permissions for these attributes**.
6. Re-ran the user creation logic.
**RESULT:** The user was created successfully. The value of `result.Succeeded` is `true`. Kindly note that phone number format needs to be `+<country_code><phonenumber>`.

Please review/correct the attribute permissions in your app client and try again.

Thanks,
Ashish
mrsuau627 commented 3 years ago

Hi @ashishdhingra ,

For me, I had the message that said "All attributes are readable and writable by default because none are selected. Select attributes to make only those readable or writable. "

I went ahead and selected all attributes to be readable and writable to rule that out as shown here: updated attributes

Please note that my issue is not the user creation logic. That works fine. The issue is after the user is created, I do the following:

                result = await _userManager.AddToRoleAsync(newUser, role.ToString());
                if (!result.Succeeded)
                {
                }

result.Succeeded is always false after AddToRoleAsync is called and contains the error that I put on my original post here. Even though Succeeded is false and there's the error, the user IS added to the correct group. Hopefully this clarifies the issue.

ashishdhingra commented 3 years ago

Please note that my issue is not the user creation logic. That works fine. The issue is after the user is created, I do the following:

                result = await _userManager.AddToRoleAsync(newUser, role.ToString());
                if (!result.Succeeded)
                {
                }

result.Succeeded is always false after AddToRoleAsync is called and contains the error that I put on my original post here. Even though Succeeded is false and there's the error, the user IS added to the correct group. Hopefully this clarifies the issue.

Hi @mrsuau627,

Thanks for the clarification. My bad, I overlooked the scenario. Unfortunately, I'm unable to reproduce the issue with the following additional steps:

  1. Created IAM role testcognito-s3-role with AmazonS3ReadOnlyAccess policy in AWS IAM console.
  2. In Cognito user pool, created group named testcognito-s3-group with role specified as testcognito-s3-role.
  3. Executed the below code (with cognitoGroup static class field set to testcognito-s3-group):
    
    var user = _pool.GetUser(Input.UserName);
    user.Attributes.Add(CognitoAttribute.Email.AttributeName, Input.Email);
    user.Attributes.Add(CognitoAttribute.FamilyName.AttributeName, lastName);
    user.Attributes.Add(CognitoAttribute.GivenName.AttributeName, firstName);
    user.Attributes.Add(CognitoAttribute.PhoneNumber.AttributeName, phoneNumber);

var result = await _userManager.CreateAsync(user, Input.Password); if (result.Succeeded) { _logger.LogInformation("User created a new account with password.");

result = await _userManager.AddToRoleAsync(user, cognitoGroup);
if (!result.Succeeded)
{
    // Handle _userManager.AddToRoleAsync error.
}

await _signInManager.SignInAsync(user, isPersistent: false);

return RedirectToPage("./ConfirmAccount");

}


**RESULT:** The value of `result.Succeeded` is `true` after call `result = await _userManager.AddToRoleAsync(user, cognitoGroup);`. The user is created successfully and added to Cognito Group `testcognito-s3-group`
<img width="1244" alt="Screen Shot 2021-02-08 at 12 43 57 PM" src="https://user-images.githubusercontent.com/67916761/107279694-379b2b80-6a0c-11eb-8c54-bc7ae1920c10.png">

Please check that you have created the group. If yes, ensure that it is mapped to proper IAM role. If this is also true, may be verify that the AWS credentials configured to execute the above code have appropriate permissions to assign users IAM role. I'm not sure what else could be done here to reproduce the issue.

I would also suggest updating the latest version of NuGet Package. As you mentioned, you also get error using latest version as well. Next (lengthy) step could be get the package source code from repository, add reference to the Cognito library project and debug it with your application to see where the error is thrown.

Thanks,
Ashish
mrsuau627 commented 3 years ago

Thanks @ashishdhingra , I have created the groups that I'm adding to, but I did not associate them to IAM roles. I'm only using the groups for role based permissions within our app, so no IAM role is needed.

I think I will take your suggestion and download the package source to debug it myself. At this point, I have 1 user pool that works correctly, and 2 that do not. I created the 1 by hand using the AWS console, and the 2 that do not work were created using Terraform. I've compared everything I can think of between the working pool and the non-working pools and I do not see any differences. It might take me a few days to get to this because of other priorities, but I will update here what I find in case someone else runs into this.

ashishdhingra commented 3 years ago

Thanks @ashishdhingra , I have created the groups that I'm adding to, but I did not associate them to IAM roles. I'm only using the groups for role based permissions within our app, so no IAM role is needed.

I think I will take your suggestion and download the package source to debug it myself. At this point, I have 1 user pool that works correctly, and 2 that do not. I created the 1 by hand using the AWS console, and the 2 that do not work were created using Terraform. I've compared everything I can think of between the working pool and the non-working pools and I do not see any differences. It might take me a few days to get to this because of other priorities, but I will update here what I find in case someone else runs into this.

Thanks. Please advise if you want to keep this guidance issue opened. I'm not sure what further guidance could be provided here since the issue is not reproducible. You can add your findings any time even if the issue is closed.

mrsuau627 commented 3 years ago

I will close the issue for now. Thanks again

github-actions[bot] commented 3 years ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

mrsuau627 commented 3 years ago

@ashishdhingra I had some time today to download the source and add it as a reference. I did some debugging and I found the spot where the error is occurring.

I checked the values being sent for the 2 different pools (1 works and 1 does not), and the attributes being sent are the same. Can you think of anything in my setup (in screenshots above) that would cause this issue?? I'm thinking of just re-creating my UserPool using the AWS Console and seeing if that works. That's the only thing I can think of is that the 1 I created using the console works, but the 2 I created with Terraform do not. Maybe it's actually a Terraform bug?

mrsuau627 commented 3 years ago

@ashishdhingra An update to my previous message. I just created a new user pool using the AWS website and it works fine. So I suspect that it's a problem with my Terraform setup or a bug with the aws_cognito_user_pool or aws_cognito_user_pool_client Terraform resources. I don't think there's anything to look at here. Just wanted to let you know. Thanks again