如何使用 boto3 在 Python 中以管理员身份从 AWS Cognito 获取 JWT 访问令牌?

mma*_*nry 7 amazon-web-services amazon-cognito boto3

我正在尝试用 Python 为我的 Web 服务编写 API 测试。我想避免使用我的 AWS Cognito 池中测试用户的密码。我对此的策略(如果有更好的方法请告诉我)是要求 API 测试以 Cognito 管理员权限运行。然后使用 boto3 库为用户获取 JWT AccessToken,我将其添加到 API 测试的每个请求的标头中。

该文档似乎没有给我一种获取 AccessToken 的方法。我想在这里使用它:https : //boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.admin_initiate_auth

admin_initiate_auth 需要三种身份验证模式之一。USER_PASSWORD_AUTH 需要密码,USER_SRP_AUTH 需要客户端密码,CUSTOM_AUTH 需要密码哈希。我希望找到一种编写此脚本的方法,以便我只需要拥有正确的 IAM 权限,而无需签入公共测试用户密码。

或者...我猜...被告知这不是一个很好的方式来做这件事,而另一种方式更合适。最终目标是对 Cognito 保护的服务进行 API 黑盒测试。

小智 6

对于我自己的项目,我也在考虑类似的策略来测试受 Cognito 保护的 API。

我认为为每次测试运行使用随机密码创建一个临时用户是一种公平的方法。

要从命令行创建用户,我认为有更简单的 cognito API 调用,即cognito-idp CLI 工具中提供的sign-upadmin-confirm-sign-up。有了这个,您可以跳过解决挑战的步骤,用户就可以使用了。

如果你想使用 boto3,这里有一个简单的函数来创建一个新用户:

def create_user(username: str, password: str, 
                user_pool_id: str, app_client_id: str) -> None:
    client = boto3.client('cognito-idp')

    # initial sign up
    resp = client.sign_up(
        ClientId=app_client_id,
        Username=username,
        Password=password,
        UserAttributes=[
            {
                'Name': 'email',
                'Value': 'test@test.com'
            },
        ]
    )

    # then confirm signup
    resp = client.admin_confirm_sign_up(
        UserPoolId=user_pool_id,
        Username=username
    )

    print("User successfully created.")
Run Code Online (Sandbox Code Playgroud)

然后,要获得 JWT,

def authenticate_and_get_token(username: str, password: str, 
                               user_pool_id: str, app_client_id: str) -> None:
    client = boto3.client('cognito-idp')

    resp = client.admin_initiate_auth(
        UserPoolId=user_pool_id,
        ClientId=app_client_id,
        AuthFlow='ADMIN_NO_SRP_AUTH',
        AuthParameters={
            "USERNAME": username,
            "PASSWORD": password
        }
    )

    print("Log in success")
    print("Access token:", resp['AuthenticationResult']['AccessToken'])
    print("ID token:", resp['AuthenticationResult']['IdToken'])
Run Code Online (Sandbox Code Playgroud)


小智 4

如果必须使用 Cognito 保护 API 测试的安全,那么您总是需要某种密码。我能想到的避免存储它的最好方法是在运行测试套件之前创建一个临时用户,然后在完成后将其删除。

您可以使用AdminCreateUser来完成此操作。在运行时生成新密码并将其作为用户的临时密码以及SUPRESS指定的MessageAction. 临时密码适用于一次登录,这就是本用例中您所需要的。然后您可以AdminInitiateAuth使用ADMIN_NO_SRP_AUTH身份验证模式运行,并指定生成的密码。测试完成后使用AdminDeleteUser进行清理。