Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 321
Attilio Gelosa Avatar asked Oct 09 '20 16:10

Attilio Gelosa


People also ask

What is a user pool in AWS Cognito?

A user pool is a user directory in Amazon Cognito. With a user pool, your users can sign in to your web or mobile app through Amazon Cognito. Your users can also sign in through social identity providers like Google, Facebook, Amazon, or Apple, and through SAML identity providers.

What is the main difference between Cognito user pool and Cognito identity pool?

With a user pool, your app users can sign in through the user pool or federate through a third-party identity provider (IdP). Identity pools are for authorization (access control). You can use identity pools to create unique identities for users and give them access to other AWS services.

How do I authenticate someone on Cognito?

2.1.Go to AWS Cognito service and click “Manage Identity Pools”. 2. Enter “Identity pool name”, expand the “Authentication providers” section and select “Cognito” tab. This is where the Cognito authentication provider will be registered with the Identity pool.

What is user pool in AWS Cognito?

The User pool is the directory where we store and manage users in AWS Cognito. The User Pool allows our users to register and sign in, and allows us to manage their user profiles. Cognito User Pool in AWS CDK - Example # The code for this article is available on GitHub

What is user/password Auth flow in AWS Cognito?

AWS Cognito User Pool is a user directory which provides sign-up and sign-in functionalities for your users. In this tutorial we will use User/Password Auth Flow managed by a Cognito App Client. A Cognito App Client is an application client which provides clients to call unauthenticated endpoints like sign-up, sign-in, forgot password etc.

What is Cognito app client in AWS?

A Cognito App Client is an application client which provides clients to call unauthenticated endpoints like sign-up, sign-in, forgot password etc. Without it users only can be added manually from AWS Console in other words by admins. Login with registered user and verify that we get a successful response which includes JWT tokens.

How do I integrate with the Amazon Cognito APIs?

To integrate with the Amazon Cognito APIs, you must have an AWS user with programmatic access. If you need information on how to get this access, see Creating IAM Users in the AWS Identity and Access Management User Guide. If you already have an account that has access to the credentials, read on.


Video Answer


1 Answers

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);
    }
}
like image 171
SOReader Avatar answered Oct 22 '22 08:10

SOReader