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

时间:2019-08-17 16:37:48

标签: amazon-web-services boto3 amazon-cognito

我正在尝试用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黑匣子测试。

2 个答案:

答案 0 :(得分:2)

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

您可以使用documentation完成此操作。在运行时生成新密码,并将其与为SUPRESS指定的MessageAction一起作为用户的临时密码传递。临时密码非常适合一次登录,这是此用例中所需要的。然后,您可以使用AdminInitiateAuth身份验证模式运行ADMIN_NO_SRP_AUTH,指定您生成的密码。测试完成后,用AdminCreateUser进行清理。

答案 1 :(得分:0)

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

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

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

如果要使用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.")

然后,获取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'])