简体   繁体   English

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

[英]How can I get a JWT Access Token from AWS Cognito as admin in Python with boto3?

I am trying to write an API test in Python for my web service.我正在尝试用 Python 为我的 Web 服务编写 API 测试。 I would like to avoid using the password of the test user from my AWS Cognito pool.我想避免使用我的 AWS Cognito 池中测试用户的密码。 My strategy for this, and let me know if there's a better way here, is to require that the API test be run with Cognito admin privileges.我对此的策略(如果有更好的方法请告诉我)是要求 API 测试以 Cognito 管理员权限运行。 Then use the boto3 library to get the JWT AccessToken for the user which I will add to the header of every request for the API test.然后使用 boto3 库为用户获取 JWT AccessToken,我将其添加到 API 测试的每个请求的标头中。

The documentation doesn't seem to give me a way to get the AccessToken.该文档似乎没有给我一种获取 AccessToken 的方法。 I'm trying to use this here: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.admin_initiate_auth我想在这里使用它: https : //boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.admin_initiate_auth

admin_initiate_auth needs one of three auth modes. admin_initiate_auth 需要三种身份验证模式之一。 USER_PASSWORD_AUTH requires the password, USER_SRP_AUTH requires a client secret, CUSTOM_AUTH requires a secret hash. USER_PASSWORD_AUTH 需要密码,USER_SRP_AUTH 需要客户端密码,CUSTOM_AUTH 需要密码哈希。 I'm hoping to find a way to write this script so that I just need to have the right IAM privileges and not need to check in a public test user password.我希望找到一种编写此脚本的方法,以便我只需要拥有正确的 IAM 权限,而无需签入公共测试用户密码。

Or... I guess... be told that this is not a great way to be doing this and that another way is more appropriate.或者...我猜...被告知这不是一个很好的方式来做这件事,而另一种方式更合适。 The end goal is to have an API black box test for a service that is secured by Cognito.最终目标是对 Cognito 保护的服务进行 API 黑盒测试。

For my own project, I was also thinking a similar strategy to test Cognito-protected APIs.对于我自己的项目,我也在考虑类似的策略来测试受 Cognito 保护的 API。

I think making a temporary user with a random password for each test run is a fair approach.我认为为每次测试运行使用随机密码创建一个临时用户是一种公平的方法。

To create a user from command line, I think there are simpler cognito API calls, which are sign-up and admin-confirm-sign-up provided in cognito-idp CLI tool.要从命令行创建用户,我认为有更简单的 cognito API 调用,即cognito-idp CLI 工具中提供的sign-upadmin-confirm-sign-up With this, you can skip the steps to resolve the challenges and the user is ready to use.有了这个,您可以跳过解决挑战的步骤,用户就可以使用了。

If you want to use boto3, here is a simple function to create a new user:如果你想使用 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.")

Then, to obtain JWT,然后,要获得 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'])

If the API test must be secured using Cognito, you're always going to need some kind of password.如果必须使用 Cognito 保护 API 测试,您总是需要某种密码。 The best way I can think of to avoid storing it is to create a temporary user before running the test suite, and then delete it when finished.我能想到的避免存储它的最好方法是在运行测试套件之前创建一个临时用户,然后在完成后将其删除。

You can use AdminCreateUser to accomplish this.您可以使用AdminCreateUser来完成此操作。 Generate a new password at runtime and pass it as the temporary password for the user, along with SUPRESS specified for MessageAction .在运行时生成一个新密码并将其作为用户的临时密码以及为MessageAction指定的SUPRESS The temporary password is good for one login, which is all you need in this use case.临时密码适用于一次登录,这是您在此用例中所需要的全部内容。 Then you can run AdminInitiateAuth with the ADMIN_NO_SRP_AUTH auth mode, specifying your generated password.然后,您可以使用ADMIN_NO_SRP_AUTH身份验证模式运行AdminInitiateAuth ,并指定您生成的密码。 Cleanup with AdminDeleteUser after the tests have finished.测试完成后使用AdminDeleteUser进行清理。

To expand on @xlem's answer and @mmachenry's comment with an example:用一个例子来扩展@xlem 的回答和@mmachenry 的评论:

Using the Cognito client of AWS SDK使用 AWS SDK 的 Cognito 客户端

  1. "AdminCreateUser" flow will create the user. “AdminCreateUser”流程将创建用户。
  2. "AdminSetPassword" will clear the FORCE_PASSWORD_CHANGE state “AdminSetPassword”将清除 FORCE_PASSWORD_CHANGE 状态
  3. "AdminInitiateAuth" will return the token “AdminInitiateAuth”将返回令牌
@pytest.fixture()
def given_a_new_user_token(request):
    client = boto3.client("cognito-idp")
    user_pool_id = "eu-west-2_xxxxxxxxx"
    username = f"test_user-{uuid.uuid4().hex}"
    temp_pwd = f"{uuid.uuid4().hex}"
    ci_test_client_id, secret_hash = get_cognito_secrets(username)

    user_response = client.admin_create_user(
        UserPoolId=user_pool_id,
        Username=username,
        UserAttributes=[
            {"Name": "email", "Value": f"{username}@example.com"},
        ],
        TemporaryPassword=temp_pwd,
        ForceAliasCreation=False,
        MessageAction="SUPPRESS",
        DesiredDeliveryMediums=[
            "EMAIL",
        ],
    )
    assert user_response["ResponseMetadata"]["HTTPStatusCode"] == 200

    def delete_user():
        client.admin_delete_user(
            UserPoolId=user_pool_id,
            Username=username,
        )

    request.addfinalizer(delete_user)

    set_pwd_response = client.admin_set_user_password(
        UserPoolId=user_pool_id,
        Username=username,
        Password=temp_pwd,
        Permanent=True
    )
    assert set_pwd_response["ResponseMetadata"]["HTTPStatusCode"] == 200

    auth_info = client.admin_initiate_auth(
        UserPoolId=user_pool_id,
        ClientId=ci_test_client_id,
        AuthFlow="ADMIN_NO_SRP_AUTH",
        AuthParameters={
            "USERNAME": username,
            "PASSWORD": temp_pwd,
            "SECRET_HASH": secret_hash,
        },
    )
    assert auth_info["ResponseMetadata"]["HTTPStatusCode"] == 200

    return auth_info["AuthenticationResult"]["AccessToken"]


def get_cognito_secrets(username: str) -> Tuple[str, str]:

    ci_test_client_id = "client_id_xxxxxxx"
    ci_test_client_secret = "client_secret_xxxxx"

    # convert str to bytes
    key = bytes(ci_test_client_secret, 'latin-1')
    msg = bytes(username + ci_test_client_id, 'latin-1')

    new_digest = hmac.new(key, msg, hashlib.sha256).digest()
    secret_hash = base64.b64encode(new_digest).decode()
    return ci_test_client_id, secret_hash

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以使用 aws cognito google oauth access_token 通过 boto3 获取临时凭证? - Is it possible to get temporary credentials via boto3 with aws cognito google oauth access_token? 如何使用AWS Cognito-身份池检索正确的凭证以在boto3客户端上访问AWS SecretsManger - How can I retrieve correct credentials to access AWS SecretsManger on a boto3 client using AWS Cognito - Indentity Pool 如何访问 Python SDK boto3 的安全令牌 - How to I access Security token for Python SDK boto3 如何通过boto3获取aws卷可用大小 - How can i get the aws volumes available size by boto3 如何使用 boto3/python 从 AWS Athena 视图中保存 SQL 脚本 - How can I save SQL script from AWS Athena view with boto3/python Python / Boto3 / 如何获得带有分页的标签列表? - Python / Boto3 / How can i get a tag list with pagination? 验证 AWS Cognito JWT 令牌(访问令牌) - Validate AWS Cognito JWT Token (Access token) Boto3:获取aws_security_token - Boto3: Get aws_security_token 从联合身份凭证获取 AWS Cognito JWT 令牌 - Get AWS Cognito JWT token from Federated Identity credentials 在AWS Cognito中调用(Admin)InitiateAuthRequest以获取具有范围的访问令牌 - Calling (Admin)InitiateAuthRequest in the AWS Cognito To Get an Access Token with Scopes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM