Attilio Gelosa
Attilio Gelosa

Reputation: 561

User management in AWS Cognito User Pool using C# and .NET Core

How to manage users within an AWS Cognito User Pool using C # and .NET Core 3.x? Couldn't find anything in the documentation about it.

Upvotes: 6

Views: 10029

Answers (2)

danielmundim
danielmundim

Reputation: 11

Just to improve on the answer of SOReader, instead of doing the steps of editing the local credentials file and using code to rely on the local profile, you could replace this behaviour by instantiating a BasicAWSCredentials object with the access key id and secret access key. The constructor method would look like something like this:

public CognitoUserManagement(RegionEndpoint regionEndpoint)
{
        adminAmazonCognitoIdentityProviderClient = new AmazonCognitoIdentityProviderClient(
            BasicAWSCredentials("access-key", "secret-key"),
            regionEndpoint);
        anonymousAmazonCognitoIdentityProviderClient = new AmazonCognitoIdentityProviderClient(
            new AnonymousAWSCredentials(),
            regionEndpoint);
}

Upvotes: 1

SOReader
SOReader

Reputation: 6047

Original article of @Attilio Gelosa

I write this article in the hope that it will help others. I had to read pages and pages of documentation and get help from the AWS experts (very many thanks, Faustino!), But in the end, I did it: being able to manage users within an AWS Cognito User Pool using C # and .NET Core 3.x.

Configuration

Before starting, we have to:

  • Do some configurations in the back-end.
  • Create a credentials file on the local machine.

Sign-in the AWS Management Console

Please, go to the AWS Management Console and sign-in with the administrative account you want to use.

Create a new user with programmatic access

Go to AWS Identity and Access Management (IAM) end click on the Users link and then click on the Add user button.

enter image description here

Type the user name you want to use, turn on the Programmatic access flag and click on the Next: Permission button.

enter image description here

Click on the Attach existing policies directly, filter the policies using "Cognito" and click on the flag to activate AmazonCognitoPowerUser

enter image description here

Click next to reach the last tab and create the user. On the next page, you will have the confirmation of the creation. Please take notes of the Access key ID value and of the Secret access key value, or you can download the CSV file containing the same information.

enter image description here

Edit the local credentials file

To edit the local credentials file, go to %USERPROFILE%\.aws\credentials if you are using Windows or using Linux ~/.aws/credentials. The file should be something like this:

[Profile_name_1]
aws_access_key_id=<ACCESS_KEY_ID_1>
aws_secret_access_key=<SECRET_ACCESS_KEY_1>

[Profile_name_2]
aws_access_key_id=<ACCESS_KEY_ID_2>
aws_secret_access_key=<SECRET_ACCESS_KEY_2>

Create a new section with the name you want and copy the access key id and secret access key you took note before. Please take note of the section name you choose.

Create a User Pool

Go to the Cognito User Pool page and create a new pool. Type the name you want to use and click on Review defaults. enter image description here

On the next page, click on Add app client... link.

enter image description here

Click on Add an app client.

enter image description here

On the next page, insert the name of the app you want to use. Make sure you turn on the following flags:

  • Enable username password auth for admin APIs for authentication (ALLOW_ADMIN_USER_PASSWORD_AUTH).
  • Enable SRP (secure remote password) protocol based authentication (ALLOW_USER_SRP_AUTH).
  • Enable refresh token-based authentication (ALLOW_REFRESH_TOKEN_AUTH).

Please note to disable the "Generate client secret" flag.

enter image description here

Finally, click on the Create app client button.

enter image description here

Now return to the pool details, clicking on the Return to pool details link.

enter image description here

Now create the new pool, clicking on the Create pool button.

enter image description here

Please note the Pool Id and the App client ID under the App client settings menu.

enter image description here

enter image description here

Create a Group

Go to Users and groups, click on the Groups tab, and then on the Create group button.

enter image description here

Type the name of the new group and click on the Create group button.

enter image description here

The code

The library code below is for demonstration purposes only. Before going into production, it is necessary to add a better exception handling system and logging.

Remember to add the following libraries:

  • Amazon.Extensions.CognitoAuthentication
  • AWSSDK.Extensions.NETCore.Setup
public class CognitoUserManagement
{
    private readonly AWSCredentials awsCredentials;
    private readonly AmazonCognitoIdentityProviderClient adminAmazonCognitoIdentityProviderClient;
    private readonly AmazonCognitoIdentityProviderClient anonymousAmazonCognitoIdentityProviderClient;

    public CognitoUserManagement(string profileName, RegionEndpoint regionEndpoint)
    {
        CredentialProfileStoreChain credentialProfileStoreChain = new CredentialProfileStoreChain();

        if (credentialProfileStoreChain.TryGetAWSCredentials(profileName, out AWSCredentials internalAwsCredentials))
        {
            awsCredentials = internalAwsCredentials;
            adminAmazonCognitoIdentityProviderClient = new AmazonCognitoIdentityProviderClient(
                awsCredentials,
                regionEndpoint);
            anonymousAmazonCognitoIdentityProviderClient = new AmazonCognitoIdentityProviderClient(
                new AnonymousAWSCredentials(),
                regionEndpoint);
        }
        else
        {
            throw new ArgumentNullException(nameof(AWSCredentials));
        }
    }

    public async Task AdminCreateUserAsync(
        string username,
        string password,
        string userPoolId,
        string appClientId,
        List<AttributeType> attributeTypes)
    {
        AdminCreateUserRequest adminCreateUserRequest = new AdminCreateUserRequest
        {
            Username = username,
            TemporaryPassword = password,
            UserPoolId = userPoolId,
            UserAttributes = attributeTypes
        };
        AdminCreateUserResponse adminCreateUserResponse = await adminAmazonCognitoIdentityProviderClient
            .AdminCreateUserAsync(adminCreateUserRequest)
            .ConfigureAwait(false);

        AdminUpdateUserAttributesRequest adminUpdateUserAttributesRequest = new AdminUpdateUserAttributesRequest
        {
            Username = username,
            UserPoolId = userPoolId,
            UserAttributes = new List<AttributeType>
                    {
                        new AttributeType()
                        {
                            Name = "email_verified",
                            Value = "true"
                        }
                    }
        };

        AdminUpdateUserAttributesResponse adminUpdateUserAttributesResponse = adminAmazonCognitoIdentityProviderClient
            .AdminUpdateUserAttributesAsync(adminUpdateUserAttributesRequest)
            .Result;


        AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest
        {
            UserPoolId = userPoolId,
            ClientId = appClientId,
            AuthFlow = "ADMIN_NO_SRP_AUTH",
            AuthParameters = new Dictionary<string, string>
            {
                { "USERNAME", username},
                { "PASSWORD", password}
            }
        };

        AdminInitiateAuthResponse adminInitiateAuthResponse = await adminAmazonCognitoIdentityProviderClient
            .AdminInitiateAuthAsync(adminInitiateAuthRequest)
            .ConfigureAwait(false);

        AdminRespondToAuthChallengeRequest adminRespondToAuthChallengeRequest = new AdminRespondToAuthChallengeRequest
        {
            ChallengeName = ChallengeNameType.NEW_PASSWORD_REQUIRED,
            ClientId = appClientId,
            UserPoolId = userPoolId,
            ChallengeResponses = new Dictionary<string, string>
                    {
                        { "USERNAME", username },
                        { "NEW_PASSWORD", password }
                    },
            Session = adminInitiateAuthResponse.Session
        };

        AdminRespondToAuthChallengeResponse adminRespondToAuthChallengeResponse = adminAmazonCognitoIdentityProviderClient
            .AdminRespondToAuthChallengeAsync(adminRespondToAuthChallengeRequest)
            .Result;
    }

    public async Task AdminAddUserToGroupAsync(
        string username,
        string userPoolId,
        string groupName)
    {
        AdminAddUserToGroupRequest adminAddUserToGroupRequest = new AdminAddUserToGroupRequest
        {
            Username = username,
            UserPoolId = userPoolId,
            GroupName = groupName
        };

        AdminAddUserToGroupResponse adminAddUserToGroupResponse = await adminAmazonCognitoIdentityProviderClient
            .AdminAddUserToGroupAsync(adminAddUserToGroupRequest)
            .ConfigureAwait(false);
    }

    public async Task<AdminInitiateAuthResponse> AdminAuthenticateUserAsync(
        string username,
        string password,
        string userPoolId,
        string appClientId)
    {
        AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest
        {
            UserPoolId = userPoolId,
            ClientId = appClientId,
            AuthFlow = "ADMIN_NO_SRP_AUTH",
            AuthParameters = new Dictionary<string, string>
            {
                { "USERNAME", username},
                { "PASSWORD", password}
            }
        };
        return await adminAmazonCognitoIdentityProviderClient
            .AdminInitiateAuthAsync(adminInitiateAuthRequest)
            .ConfigureAwait(false);
    }

    public async Task AdminRemoveUserFromGroupAsync(
        string username,
        string userPoolId,
        string groupName)
    {
        AdminRemoveUserFromGroupRequest adminRemoveUserFromGroupRequest = new AdminRemoveUserFromGroupRequest
        {
            Username = username,
            UserPoolId = userPoolId,
            GroupName = groupName
        };

        await adminAmazonCognitoIdentityProviderClient
            .AdminRemoveUserFromGroupAsync(adminRemoveUserFromGroupRequest)
            .ConfigureAwait(false);
    }

    public async Task AdminDisableUserAsync(
        string username,
        string userPoolId)
    {
        AdminDisableUserRequest adminDisableUserRequest = new AdminDisableUserRequest
        {
            Username = username,
            UserPoolId = userPoolId
        };

        await adminAmazonCognitoIdentityProviderClient
            .AdminDisableUserAsync(adminDisableUserRequest)
            .ConfigureAwait(false);
    }

    public async Task AdminDeleteUserAsync(
        string username,
        string userPoolId)
    {
        AdminDeleteUserRequest deleteUserRequest = new AdminDeleteUserRequest
        {
            Username = username,
            UserPoolId = userPoolId
        };

        await adminAmazonCognitoIdentityProviderClient
            .AdminDeleteUserAsync(deleteUserRequest)
            .ConfigureAwait(false);
    }
}

Upvotes: 16

Related Questions