Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get authenticated identity response from AWS Cognito using boto3

I would like to use boto3 to get temporary credentials for access AWS services. The use case is this: A user in my Cognito User Pool logs in to my server and I want the server code to provide that user with temporary credentials to access other AWS services.

I have a Cognito User Pool where my users are stored. I have a Cognito Identity Pool that does NOT allow unauthorized access, only access by users from the Cognito User Pool.

So here is the code I am starting with:

import boto3
client = boto3.client('cognito-identity','us-west-2')
resp = client.get_id(AccountId='<ACCNTID>',
                     IdentityPoolId='<IDPOOLID>')

However, just running these three lines of code throws an exception:

botocore.errorfactory.NotAuthorizedException: An error 
occurred (NotAuthorizedException) when calling 
the GetId operation: Unauthenticated access is not 
supported for this identity pool.

Since my Cognito Identity Pool is not set up for unauthenticated access, it seems that I cannot call get_id until I somehow authenticate somewhere.

How do I solve this? What exactly do I need to do to authenticate so I can call get_id?

UPDATE: Looks like I need to pass a Logins field and data to the get_id function call, but to do that I need the login JWT token. If I am running this inside a webapp (eg a Django backend) where I use the AWS Cognito prepackaged login screens, then yes I can get this from the homepage URL after redirection from successful login. But now I am writing some test scripts that have nothing to do with a website. Is there a way to use boto or boto3 or some other python package to login with username and password and get JWT token?

like image 614
Marc Avatar asked Apr 24 '19 02:04

Marc


2 Answers

Just to add to the answer from Arka Mukherjee above, to get the token I do this:

auth_data = { 'USERNAME':username , 'PASSWORD':password }
provider_client=boto3.client('cognito-idp', region_name=region)
resp = provider_client.admin_initiate_auth(UserPoolId=user_pool_id, AuthFlow='ADMIN_NO_SRP_AUTH', AuthParameters=auth_data, ClientId=client_id)
token = resp['AuthenticationResult']['IdToken']

Here I have to use the username and password of the Cognito user, client_id is the app client id for the app client that I set up thru Cognito, and user_pool_id is the user pool id.

Note that my app client has this option checked/selected: Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH) and I created that app client with no secret key (apparently that is important for web clients especially).

like image 180
Marc Avatar answered Nov 01 '22 02:11

Marc


To pass the Cognito User Pool JWT Token, you would need to use the Logins Map in the GetId API call. You could try the following Python code out on your end, after replacing the necessary placeholders.

response = client.get_id(
    AccountId='string',
    IdentityPoolId='string',
    Logins={
        'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>': '<JWT ID Token>'
    }
)

If you do not provide a Logins Map, Amazon Cognito treats the authentication event as Unauthenticated, and hence, you are facing this error.

like image 44
Arka Mukherjee Avatar answered Nov 01 '22 00:11

Arka Mukherjee