Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. I would like to avoid using the password of the test user from my AWS Cognito pool. 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. 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.

The documentation doesn't seem to give me a way to get the 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

admin_initiate_auth needs one of three auth modes. USER_PASSWORD_AUTH requires the password, USER_SRP_AUTH requires a client secret, CUSTOM_AUTH requires a secret hash. 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.

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.

like image 309
mmachenry Avatar asked Aug 17 '19 16:08

mmachenry


1 Answers

For my own project, I was also thinking a similar strategy to test Cognito-protected APIs.

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. 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:

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': '[email protected]'
            },
        ]
    )

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

    print("User successfully created.")

Then, to obtain 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'])
like image 154
Tomoyuki Mano Avatar answered Sep 20 '22 08:09

Tomoyuki Mano