Build a Secure MFA‑Enabled AWS CLI Login with Cognito
This guide shows how to replace limited IAM Identity Center access by creating a lightweight, MFA‑protected CLI login portal using AWS Cognito user pools and identity pools, generating temporary STS credentials and automating the process with a Python/Boto3 script.
Background
When IAM Identity Center is unavailable (e.g., in a single‑account setup or when accessed through a partner), the AWS CLI cannot use aws configure sso. To avoid static IAM user keys, you can build an MFA‑protected login flow with Amazon Cognito that issues temporary STS credentials for CLI use.
Why Cognito?
Cognito satisfies three essential requirements:
Authenticate the user (with optional MFA).
Issue short‑lived AWS STS credentials after successful authentication.
Be scriptable so the flow can be automated for the CLI.
It acts as a lightweight, self‑hosted “mini‑IAM Identity Center” compared with heavyweight solutions such as AWS Managed Microsoft AD.
Core Architecture
The solution combines two Cognito components:
User Pool : Stores user accounts and enforces MFA. It only performs authentication.
Identity Pool : Trusts the authenticated user from the User Pool and exchanges the ID token for IAM role‑based temporary credentials (authorization).
Data flow:
CLI → Cognito User Pool (username + password + MFA) → ID token → Cognito Identity Pool (exchange token) → Temporary AWS credentials (AccessKeyId, SecretAccessKey, SessionToken)Step‑by‑Step Implementation
Step 1 – Create a Cognito User Pool
Open the Cognito console and choose **Create user pool**.
During the login‑experience configuration, select **Cognito user pool** as the provider type.
In the **Multi‑Factor Authentication (MFA)** section set **Required** and pick **Authenticator apps** (e.g., Google Authenticator).
Leave other settings at their defaults and finish creating the pool.
Manually add a user (e.g., dave) and complete the initial password and MFA device setup.
Step 2 – Create a Cognito Identity Pool
In the Cognito console switch to **Federated Identities** and click **Create new identity pool**.
Give the pool a name, then expand **Authentication providers**.
Select the **Cognito** tab and provide the **User Pool ID** and **App Client ID** created in Step 1.
Accept the prompt to create a new IAM role for the identity pool; this role will be assumed after login.
Step 3 – Configure IAM Role Permissions
Open the IAM console, locate the role automatically generated for the identity pool (its name contains the identity‑pool identifier).
Attach the policies that define the CLI permissions you need. For full admin rights attach AdministratorAccess; for limited S3 access attach the appropriate S3 policy.
Step 4 – Write the CLI Login Script
The AWS CLI does not provide a built‑in aws configure cognito command, so a custom script is required. Below is a Python example using Boto3.
import boto3
import getpass
import configparser
import os
# --- Configuration (replace with your own values) ---
USER_POOL_ID = 'us-east-1_xxxxxxxxx' # Cognito User Pool ID
CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxx' # App Client ID
IDENTITY_POOL_ID = 'us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' # Identity Pool ID
REGION = 'us-east-1' # AWS region
ROLE_ARN = 'arn:aws:iam::123456789012:role/Cognito_YourIdentityPoolAuth_Role' # Role created in Step 3
def get_cognito_tokens(username, password):
client = boto3.client('cognito-idp', region_name=REGION)
try:
# Initiate USER_PASSWORD_AUTH flow
resp = client.initiate_auth(
ClientId=CLIENT_ID,
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={'USERNAME': username, 'PASSWORD': password}
)
# Handle MFA challenge if present
if resp.get('ChallengeName') == 'SOFTWARE_TOKEN_MFA':
mfa_code = input('Enter MFA code: ')
resp = client.respond_to_auth_challenge(
ClientId=CLIENT_ID,
ChallengeName='SOFTWARE_TOKEN_MFA',
Session=resp['Session'],
ChallengeResponses={
'USERNAME': username,
'SOFTWARE_TOKEN_MFA_CODE': mfa_code,
}
)
return resp['AuthenticationResult']['IdToken']
except client.exceptions.NotAuthorizedException:
print('Error: Invalid username or password.')
return None
except Exception as e:
print(f'Unexpected error: {e}')
return None
def get_aws_credentials(id_token):
client = boto3.client('cognito-identity', region_name=REGION)
# Exchange ID token for an Identity ID
identity_id_resp = client.get_id(
IdentityPoolId=IDENTITY_POOL_ID,
Logins={f'cognito-idp.{REGION}.amazonaws.com/{USER_POOL_ID}': id_token}
)
identity_id = identity_id_resp['IdentityId']
# Retrieve temporary AWS credentials for that identity
creds_resp = client.get_credentials_for_identity(
IdentityId=identity_id,
Logins={f'cognito-idp.{REGION}.amazonaws.com/{USER_POOL_ID}': id_token}
)
return creds_resp['Credentials']
def update_aws_config(credentials):
aws_config_path = os.path.expanduser('~/.aws/credentials')
config = configparser.ConfigParser()
if os.path.exists(aws_config_path):
config.read(aws_config_path)
profile_name = 'cognito-sso'
if not config.has_section(profile_name):
config.add_section(profile_name)
config.set(profile_name, 'aws_access_key_id', credentials['AccessKeyId'])
config.set(profile_name, 'aws_secret_access_key', credentials['SecretAccessKey'])
config.set(profile_name, 'aws_session_token', credentials['SessionToken'])
with open(aws_config_path, 'w') as configfile:
config.write(configfile)
print(f"Credentials saved to profile '{profile_name}'.")
print('Test with: aws s3 ls --profile cognito-sso')
if __name__ == '__main__':
username = input('Username: ')
password = getpass.getpass('Password: ')
id_token = get_cognito_tokens(username, password)
if id_token:
credentials = get_aws_credentials(id_token)
update_aws_config(credentials)Using the Script
Install Boto3: pip install boto3 Replace the configuration constants at the top of the script with your Cognito User Pool ID, App Client ID, Identity Pool ID, region, and the IAM role ARN created in Step 3.
Run the script: python login.py Enter your username, password, and MFA code when prompted.
The script writes temporary credentials to a new profile named cognito-sso in ~/.aws/credentials.
Subsequent CLI commands can use the profile, e.g., aws s3 ls --profile cognito-sso.
Conclusion
By combining a Cognito User Pool (authentication + MFA) with a Cognito Identity Pool (authorization), you can create a lightweight, secure CLI login flow that provides short‑lived STS credentials without relying on organization‑level IAM Identity Center. The same pattern can be extended to secure access for applications or additional team members.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Development & AI Practice
DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
