且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 C# 和 .NET Core 在 AWS Cognito 用户池中管理用户

更新时间:2023-02-16 14:58:55

@Attilio Gelosa 原创文章

Original article of @Attilio Gelosa

我写这篇文章是希望它能帮助别人.我不得不阅读一页又一页的文档并从 AWS 专家那里获得帮助(非常感谢,Faustino!),但最终我做到了:能够使用 C# 和 .NET 核心 3.x.

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.

在开始之前,我们必须:

Before starting, we have to:

  • 在后端做一些配置.
  • 在本地计算机上创建凭据文件.

请转至 AWS 管理控制台并使用您要使用的管理账户登录.

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

转到 AWS Identity and Access Management (IAM) 最后点击用户链接,然后点击添加用户按钮.

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

键入您要使用的用户名,打开程序访问标志,然后单击下一步:权限按钮.

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

点击直接附加现有政策,使用Cognito"过滤政策并单击该标志以激活 AmazonCognitoPowerUser

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

单击下一步以到达最后一个选项卡并创建用户.在下一页,您将获得创建确认.请记下访问密钥 ID 值和秘密访问密钥值,或者您可以下载包含相同信息的 CSV 文件.

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.

要编辑本地凭据文件,如果您使用的是 Windows 或 Linux ~/.aws/credentials,请转到 %USERPROFILE%.awscredentials.该文件应该是这样的:

To edit the local credentials file, go to %USERPROFILE%.awscredentials 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>

使用您想要的名称创建一个新部分,并复制您之前记下的访问密钥 ID 和秘密访问密钥.请记下您选择的部分名称.

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.

转到 Cognito 用户池页面并创建一个新池.输入您要使用的名称,然后单击查看默认值.

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

在下一页上,点击添加应用客户端...链接.

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

点击添加应用客户端.

在下一页上,插入您要使用的应用程序的名称.确保打开以下标志:

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

  • 为管理员 API 启用用户名密码身份验证以进行身份​​验证 (ALLOW_ADMIN_USER_PASSWORD_AUTH).
  • 启用基于 SRP(安全远程密码)协议的身份验证 (ALLOW_USER_SRP_AUTH).
  • 启用基于刷新令牌的身份验证 (ALLOW_REFRESH_TOKEN_AUTH).

请注意禁用生成客户端密码"标志.

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

最后,点击创建应用客户端按钮.

现在返回池详细信息,点击返回池详细信息链接.

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

现在创建新池,点击创建池按钮.

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

请注意应用客户端设置菜单下的池ID应用客户端ID.

转到用户和群组,点击群组标签,然后点击创建群组按钮.

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

输入新组的名称并点击创建组按钮.

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

下面的库代码仅用于演示目的.在投入生产之前,有必要添加一个更好的异常处理系统和日志记录.

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.

记得添加以下库:

  • 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);
    }
}