Amazon Cognito user authorization using IAM roles and accessing AWS services using temporary credentials
INTRODUCTION
In most of the scenarios where we have applications and Amazon Cognito being used as an User Authentication and Authorization, there are requirements of accessing AWS services depending on the user roles. Access to application users depends on the user groups or roles which are tied to the Business application of the web application. Thus it becomes necessary to tie back the application users to the AWS service access depending on the authorization levels defined
Today, we are going to see how to achieve this functionality in any kind of web application. For this we are going to implement the above access methodology defined in the architecture image shown. So let’s get started with the implementation
Step 1: Generate the ID Tokens using User Credentials
At this step, we need to understand that, the user is already registered in the Amazon Cognito User pool and there are Cognito groups defined, where the user is part of the group.
Every Cognito group have been assigned an IAM role which defines AWS service level access for the users. These IAM roles are also defined in the AWS Lake formation principals which defined the AWS Database and tables access in Glue Data Catalog
import boto3
client=boto3.client("cognito-idp")
#Add your Cognito Identity Pool ID in this variable
identityPoolId='<Cognito-Identity-PoolID>'
#Define the User Credentials for the user for which Token's needs to be generated
user_name='<UserName>'
user_password='<User-Passowrd>'
#Define the Client ID for the application defined in the Cognito User Pool
client_id='<Cognito-application-client-id>'
response = client.initiate_auth(
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': user_name,
'PASSWORD': user_password
},
ClientId=client_id
)
In the above code, we are defining the User credentials and then the Cognito application client id which is registered with the Cognito user pool. The response that we will get will be the tokens of the users
If the user’s credentials are correct then you will get response of the above boto3 API and then you can check the response variable which will be the Cognito token id
STEP 2: Pass the Cognito ID Token and then generate the Identity id
At this step we will be passing the previously obtained Cognito ID token and then will be getting the Identity ID for the user. For this we need to define the Identity Pool ID (identityPoolId) which we have already defined in the previous step.
cognito_IdToken=response['AuthenticationResult']['IdToken']
print(cognito_IdToken)
cog_client=boto3.client("cognito-identity")
#Need to define the Cognito IDPusing the URL as cognito-idp.<region>.amazonaws.com/<user-pool-id>
response = cog_client.get_id(IdentityPoolId=identityPoolId, Logins={'cognito-idp.<region>.amazonaws.com/<user-pool-id>': cognito_IdToken})
Then we create cognito-identity client using boto3 and then use the get_id API. Once we hit this API we will get the identity id for the user
Once we get the identity id, we need to generate the temporary user credentials using the API
STEP 3: Pass the Identity ID and then generate the temporary user credentials
At this stage the Identity ID which we received from the previous API call will be leveraged to call the get_credentials_for_identity API and generate the temporary credentials of the user
IdentityId=response['IdentityId']
#Need to define the Cognito IDPusing the URL as cognito-idp.<region>.amazonaws.com/<user-pool-id>
response = cog_client.get_credentials_for_identity(IdentityId=IdentityId, Logins={'cognito-idp.<region>.amazonaws.com/<user-pool-id>': cognito_IdToken})
access_key_id=response['Credentials']['AccessKeyId']
secret_key=response['Credentials']['SecretKey']
session_token=response['Credentials']['SessionToken']
print("Access Key ID : "+str(access_key_id))
print("Access Scret Key : "+str(secret_key))
print("Session Key : "+str(session_token))
STEP 4: Leverage the temporary credentials to access the AWS services
Now, after we got the AWS Secret keys of the users, then we can access the AWS services using boto3 APIs. For that we need to define the temporary credentials while creating the client of the server. Just follow the following code for the same
s3_client = boto3.client(
's3',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_key,
aws_session_token=session_token
)
response = s3_client.list_objects_v2(
Bucket='<S3-bucket-name>'
)
athena_client = boto3.client('athena',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_key,
aws_session_token=session_token
)
response = athena_client.start_query_execution(
QueryString='SELECT * FROM "<database-name>"."<table-name>" limit 100;',
WorkGroup='primary'
)
This is the way in which you can access the various AWS services depending on the user who is logged in to the application by generating the user specific temporary credentials. Thus all the APIs in which we will be using these credentials will only be getting the access defined for the user which has been defined in the cognito
In case if the user does not have access to a specific S3 bucket or a specific Database and table in the Glue data Catalog, the APIs will give an error as Access Denied, as shown in the image below.
CONCLUSION:
Amazon Cognito User Pools serves as a robust and scalable solution for managing user authentication and authorization in web and mobile applications. With its seamless integration with other AWS services, extensive support for various authentication methods, and built-in security features, Cognito User Pools empowers developers to rapidly build and deploy secure applications without the complexities of managing user identities.
By offering features such as multi-factor authentication, user profile management, and fine-grained access control, Cognito User Pools enables organizations to deliver a seamless and secure user experience while maintaining compliance with industry standards and regulations. As a foundational component of the AWS ecosystem, Cognito User Pools plays a pivotal role in enabling organizations to innovate and deliver value to their users in today’s digital landscape.
REFERENCES:
- Amazon Cognito Overview — https://aws.amazon.com/cognito/
- Amazon Cognito User Pools — https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html
- Amazon Cognito Identity Pools — https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html
- Get Credentials -https://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html
- Amazon Cognito with token generation — https://aws.amazon.com/blogs/publicsector/getting-started-healthcare-data-lakes-deeper-dive-amazon-cognito/