Introduction
To use the AWS Python SDK (boto3) with SSO credentials, configure an SSO profile in ~/.aws/config, run aws sso login --profile your-profile to authenticate, then create a boto3 session with boto3.Session(profile_name='your-profile'). Boto3 automatically reads the cached SSO token and exchanges it for temporary AWS credentials. This avoids storing long-lived access keys and integrates with your organization's identity provider (Okta, Azure AD, etc.) through AWS IAM Identity Center (formerly AWS SSO).
1# ~/.aws/config
2[profile dev-admin]
3sso_session = my-sso
4sso_account_id = 123456789012
5sso_role_name = AdministratorAccess
6region = us-east-1
7
8[sso-session my-sso]
9sso_start_url = https://my-company.awsapps.com/start
10sso_region = us-east-1
11sso_registration_scopes = sso:account:access
For the legacy (pre-session) format:
1# Legacy format (still works)
2[profile dev-admin]
3sso_start_url = https://my-company.awsapps.com/start
4sso_region = us-east-1
5sso_account_id = 123456789012
6sso_role_name = AdministratorAccess
7region = us-east-1
Step 2: Log In via CLI
1# Authenticate — opens browser for SSO login
2aws sso login --profile dev-admin
3
4# Verify credentials work
5aws sts get-caller-identity --profile dev-admin
6# {
7# "Account": "123456789012",
8# "Arn": "arn:aws:sts::123456789012:assumed-role/AdministratorAccess/[email protected]",
9# "UserId": "AROA..."
10# }
Step 3: Use boto3 with the SSO Profile
1import boto3
2
3# Create a session with the SSO profile
4session = boto3.Session(profile_name='dev-admin')
5
6# Use any AWS service
7s3 = session.client('s3')
8buckets = s3.list_buckets()
9for bucket in buckets['Buckets']:
10 print(bucket['Name'])
11
12# EC2 example
13ec2 = session.client('ec2')
14instances = ec2.describe_instances()
15for reservation in instances['Reservations']:
16 for instance in reservation['Instances']:
17 print(f"{instance['InstanceId']}: {instance['State']['Name']}")
Using Environment Variables
1# Set the profile via environment variable
2export AWS_PROFILE=dev-admin
3
4# Now boto3 uses it automatically without specifying profile_name
5python -c "import boto3; print(boto3.client('sts').get_caller_identity())"
1import os
2import boto3
3
4# Or set in Python
5os.environ['AWS_PROFILE'] = 'dev-admin'
6session = boto3.Session() # Picks up AWS_PROFILE
7s3 = session.client('s3')
Multiple Accounts and Roles
1# ~/.aws/config — multiple profiles for different accounts/roles
2[sso-session my-sso]
3sso_start_url = https://my-company.awsapps.com/start
4sso_region = us-east-1
5
6[profile dev-admin]
7sso_session = my-sso
8sso_account_id = 111111111111
9sso_role_name = AdministratorAccess
10region = us-east-1
11
12[profile staging-readonly]
13sso_session = my-sso
14sso_account_id = 222222222222
15sso_role_name = ReadOnlyAccess
16region = us-west-2
17
18[profile prod-deploy]
19sso_session = my-sso
20sso_account_id = 333333333333
21sso_role_name = DeployRole
22region = us-east-1
1import boto3
2
3# Switch between accounts/roles by profile
4dev_session = boto3.Session(profile_name='dev-admin')
5staging_session = boto3.Session(profile_name='staging-readonly')
6prod_session = boto3.Session(profile_name='prod-deploy')
7
8# Each session has its own credentials
9dev_s3 = dev_session.client('s3')
10staging_ec2 = staging_session.client('ec2')
11prod_lambda = prod_session.client('lambda')
Handling Token Expiration
1import boto3
2from botocore.exceptions import UnauthorizedSSOTokenError, TokenRetrievalError
3import subprocess
4import sys
5
6def get_session(profile_name='dev-admin'):
7 session = boto3.Session(profile_name=profile_name)
8
9 try:
10 # Test if credentials are valid
11 sts = session.client('sts')
12 sts.get_caller_identity()
13 return session
14 except (UnauthorizedSSOTokenError, TokenRetrievalError):
15 print("SSO token expired. Re-authenticating...")
16 subprocess.run(['aws', 'sso', 'login', '--profile', profile_name], check=True)
17 return boto3.Session(profile_name=profile_name)
18
19session = get_session()
20s3 = session.client('s3')
21print(s3.list_buckets()['Buckets'])
Programmatic SSO Token Refresh
1import boto3
2
3# Using the SSO OIDC client for programmatic login (headless environments)
4session = boto3.Session(region_name='us-east-1')
5sso_oidc = session.client('sso-oidc')
6
7# Register a client
8client_info = sso_oidc.register_client(
9 clientName='my-app',
10 clientType='public'
11)
12
13# Start device authorization
14auth_response = sso_oidc.start_device_authorization(
15 clientId=client_info['clientId'],
16 clientSecret=client_info['clientSecret'],
17 startUrl='https://my-company.awsapps.com/start'
18)
19
20print(f"Open this URL: {auth_response['verificationUriComplete']}")
21print(f"Enter code: {auth_response['userCode']}")
22
23# Poll for token (after user authorizes in browser)
24import time
25while True:
26 try:
27 token = sso_oidc.create_token(
28 clientId=client_info['clientId'],
29 clientSecret=client_info['clientSecret'],
30 grantType='urn:ietf:params:oauth:grant-type:device_code',
31 deviceCode=auth_response['deviceCode']
32 )
33 break
34 except sso_oidc.exceptions.AuthorizationPendingException:
35 time.sleep(auth_response['interval'])
36
37# Use the token to get role credentials
38sso = session.client('sso')
39credentials = sso.get_role_credentials(
40 roleName='AdministratorAccess',
41 accountId='123456789012',
42 accessToken=token['accessToken']
43)['roleCredentials']
44
45# Create a session with the temporary credentials
46authed_session = boto3.Session(
47 aws_access_key_id=credentials['accessKeyId'],
48 aws_secret_access_key=credentials['secretAccessKey'],
49 aws_session_token=credentials['sessionToken']
50)
Common Pitfalls
Forgetting to run aws sso login before using boto3: SSO credentials require an active login session. Without it, boto3 raises UnauthorizedSSOTokenError or TokenRetrievalError. Run aws sso login --profile your-profile and complete the browser authentication before running Python scripts.
SSO token expiration during long-running scripts: SSO tokens typically expire after 1-8 hours (configurable by the admin). Long-running scripts fail midway when the token expires. Wrap API calls in try-except for token errors and re-authenticate, or use sso_registration_scopes with longer session durations.
Using boto3.client() instead of boto3.Session().client(): boto3.client('s3') uses the default session, which may not pick up your SSO profile. Always create an explicit session: session = boto3.Session(profile_name='dev-admin') then session.client('s3').
Mixing SSO config formats (legacy vs session): The legacy format (all SSO fields in the profile) and the session format (sso_session reference) are not interchangeable. Mixing them in the same profile causes InvalidConfigError. Use one format consistently — the session format is recommended for token portability.
Running in CI/CD without interactive login: SSO login requires a browser. In CI/CD environments, use IAM roles (instance profiles, OIDC federation) instead of SSO, or use aws sso login with device authorization in a pre-step that caches the token for subsequent jobs.
Summary
Configure an SSO profile in ~/.aws/config with sso_start_url, sso_account_id, and sso_role_name
Run aws sso login --profile name to authenticate, then use boto3.Session(profile_name='name')
Handle token expiration with try-except and re-authentication for long-running scripts
Use multiple profiles in ~/.aws/config to switch between accounts and roles
Set AWS_PROFILE environment variable to avoid specifying profile_name in every session