Open a terminal and run this:
cat ~/.aws/credentials
If you see something like this:
[default]
aws_access_key_id = ...
aws_secret_access_key = .../...
You have a problem. Those are long-lived static credentials sitting in plain text on your laptop. This post explains why that is dangerous and walks you through fixing it properly using AWS IAM Identity Center.
1. Why This Matters — The Problem With What You Probably Have
The bad practice
When most people start with AWS they do something like this: create an access key, run aws configure, paste the key in, and get to work. It takes five minutes and it works. The problem is what you end up with:
- A permanent key that never expires unless you manually rotate it
- That key in plain text in
~/.aws/credentials - Possibly committed to a git repo, copied into CI/CD pipelines, or living in
.envfiles across your projects - If those credentials belong to root — unlimited, unrestricted access to everything in your account
One accidental git push, one leaked dotfile, one compromised laptop — and someone can run up thousands of dollars in crypto mining charges before you notice. This happens constantly. Search for it and you will find no shortage of horror stories.
Why root credentials are especially dangerous
The AWS root user is not just a very powerful IAM user. It exists outside the IAM system entirely. No policy can restrict it. No permission boundary applies to it. If someone gets root credentials they can close your account, remove MFA, and delete all your resources — and no IAM policy you write can stop them.
AWS itself says it clearly in their IAM best practices:
Safeguard your root user credentials and don't use them for everyday tasks.
The fix
Replace static credentials with temporary credentials that expire automatically. The modern AWS way to do this is IAM Identity Center — you log in via browser, get credentials that last a few hours, and nothing sensitive ever sits on disk permanently.
2. Concepts and Vocabulary
Before touching the console, make sure these terms are clear. AWS documentation uses them constantly and mixing them up is where most confusion starts.
AWS Account
The top-level container. Everything you create in AWS — EC2 instances, S3 buckets, Lambda functions — lives
inside an account. An account is identified by a 12-digit ID like 089123123123. You can have
multiple accounts (one for dev, one for prod, etc.).
Root User
The identity created when you first sign up for an AWS account. Identified by the email address you used. It has unlimited power and cannot be restricted. Use it only for the handful of tasks AWS requires root for (like closing the account). Lock it away with MFA and never create access keys for it.
IAM User
A permanent identity inside the IAM service. Has a username, password, and optionally access keys. IAM users made sense in 2010. Today they are discouraged for human access because they have long-lived credentials that are easy to mishandle. AWS's own documentation now recommends against them for most cases. See: IAM Users.
IAM Role
A temporary identity that can be assumed by a principal (a person, a service, an application). When you assume a role, AWS gives you short-lived credentials for that session. Roles are the foundation of secure AWS access — everything modern in AWS uses them.
IAM Policy
A JSON document that says what actions are allowed or denied on which resources. Policies are attached to roles (or users). They are the answer to: what can this identity actually do?
AWS Organizations
A service that groups multiple AWS accounts under one management structure. Even if you only have one account today, enabling Organizations is the right first step — it is free, it unlocks IAM Identity Center, and it prepares you for multi-account setups later. See: AWS Organizations.
IAM Identity Center
The modern central place to manage human access to AWS accounts. Formerly called AWS SSO (Single Sign-On). It manages users, groups, and permission sets. It issues temporary credentials on login. It is free. See: IAM Identity Center docs.
Permission Set
An IAM Identity Center concept. Think of it as a named role template — for example, AdministratorAccess
or ReadOnly. You assign a permission set to a user on a specific account. IAM Identity Center
creates the actual IAM role behind the scenes.
SSO Session
A named configuration in your local ~/.aws/config that points to your IAM Identity Center portal.
When you run aws sso login, it uses this session to know where to authenticate you. You can have
multiple sessions for different AWS organisations (personal, client A, client B, etc.).
3. Services Used
All these services are free. Placed in order of setup.
| Service | Purpose in this setup |
|---|---|
| AWS Organizations | Groups accounts together. Required for IAM Identity Center organization instance. |
| AWS Identity and Access Management (IAM) | Classic identity service. Still used underneath — Identity Center creates IAM roles behind the scenes. |
| AWS IAM Identity Center | Manages SSO users, permission sets, and account assignments. Issues temporary credentials. |
| AWS Security Token Service (STS) | Issues short-lived temporary credentials when you log in. You never interact with it directly. |
4. Setting Up IAM Identity Center — Step by Step
You need to be logged into the AWS console as root for the first few steps. After setup, root goes back in the drawer permanently.
Step 1 — Secure root first
Root should have MFA and no access keys. Check now:
- In the console, top-right corner → your account name → Security credentials
- Under Multi-factor authentication — confirm MFA is enabled. If not, add it now. A hardware security key (FIDO2/U2F) is best. An authenticator app is fine.
- Under Access keys — if any key exists, deactivate and delete it. Root should never have an access key.
Step 2 — Enable billing access for IAM identities
By default, even an admin SSO user cannot see your billing console. Fix this now while you are still in root:
- Top-right → your account name → Security credentials
- Scroll to IAM user and role access to Billing information → Edit
- Check Activate IAM Access → Update
Step 3 — Enable AWS Organizations
- Search for AWS Organizations in the console search bar
- Click Create an organization → confirm
Your account becomes the management account. This is free and does not change how your account works. You will also see a banner offering to centralise root access for member accounts — click Enable in IAM. This lets you manage root credentials of any future member accounts centrally, which is a security best practice.
Step 4 — Enable IAM Identity Center
Important: Change your AWS region before clicking Enable. IAM Identity Center is regional and cannot be moved later without deleting it and starting over. Pick the region nearest to you or your team.
- Change region in the top-right dropdown — e.g.
ap-northeast-1for Tokyo - Search for IAM Identity Center
- Click Enable → Enable with AWS Organizations
You will see a success message with a new instance ID. Keep this page open.
Step 5 — Create your SSO admin user
This is the identity you will use for all daily work from now on. Not root. Not an IAM user.
- IAM Identity Center left menu → Users → Add user
- Fill in: username (e.g.
yourname-admin), email address, first and last name - Click through to Add user
- Check your email for an invitation from
no-reply@login.awsapps.com - Click the invite link, set a password, and set up MFA on this user too
Step 6 — Create a Permission Set
- Left menu → Permission sets → Create permission set
- Choose Predefined permission set
- Select AdministratorAccess
- Keep the default name → Create
For a personal account, AdministratorAccess is fine — you are the only user.
For team or client work you would later create scoped-down sets like TerraformDeploy or ReadOnly.
Step 7 — Assign the user to your account
- Left menu → AWS accounts
- Check the checkbox next to your account
- Click Assign users or groups
- Select your SSO user → Next
- Select
AdministratorAccess→ Next → Submit
AWS provisions a real IAM role behind the scenes with a trust policy allowing your SSO user to assume it. You never manage that role directly.
Step 8 — Note your portal URL
Left menu → Dashboard. You will see your AWS access portal URL:
https://d-xxxxxxxxxx.awsapps.com/start
Save this. It is your login page from now on — not console.aws.amazon.com. You can customise
it under Settings → Identity source.
Step 9 — Clean up old credentials
Delete the old access key from AWS first — deleting the local file is not enough, the key still works in AWS until you revoke it there.
- Console → top-right → Security credentials (while logged in as whichever IAM user owned the key)
- Scroll to Access keys → deactivate → Delete
Then clean up locally:
# Wipe the credentials file
> ~/.aws/credentials
# Also check for other places like:
# ~/.zshrc ~/.bashrc ~/.bash_profile ~/.zprofile
# *.tf, *.env, *.tfvars
Step 10 — Configure the AWS CLI with SSO
aws configure sso
Answer the prompts:
SSO session name (Recommended): personal
SSO start URL [None]: https://d-xxxxxxxxxx.awsapps.com/start
SSO region [None]: ap-northeast-1
SSO registration scopes [sso:account:access]: [press Enter]
# A browser opens — log in as your SSO user and authorise the CLI
Default client Region [None]: ap-northeast-1
CLI default output format [None]: json
CLI profile name [AdministratorAccess]: admin
Your ~/.aws/config now looks like this. No credentials file. No keys anywhere.
[profile admin]
sso_session = personal
sso_account_id = 123456789012
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json
[sso-session personal]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access
5. Verify Everything Works
Log in and confirm your identity:
aws sso login --sso-session personal
aws sts get-caller-identity --profile admin
You should see output like this:
{
"UserId": "AROAXXXXXXXXXXXXXXXXX:yourname-admin",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_AdministratorAccess_xxx/yourname-admin"
}
Three things to confirm in that output:
- UserId ends with your SSO username — not root, not an IAM user
- Arn contains
assumed-role— you are using a temporary role, not permanent credentials - Account is your correct account ID
When the session expires (typically after 8 hours), just run aws sso login --sso-session personal
again. That is your entire credential management workflow now.
5.1. Bonus: Try with Terraform
Use it with Terraform by setting the profile:export AWS_PROFILE=admin
terraform init
terraform plan
Or in your provider.tf:
provider "aws" {
region = "ap-northeast-1"
profile = "admin"
}
6. Before and After
| Before | After | |
|---|---|---|
| Identity | Root user or IAM user | SSO user (yourname-admin) |
| Credentials type | Static — never expire | Temporary — expire in hours |
| Stored where | Plain text in ~/.aws/credentials |
Nowhere — fetched fresh on each login |
| Rotation | Manual — easy to forget | Automatic — always |
| If credentials leak | Permanent access until manually revoked | Expires on its own within hours |
| Multi-account ready | No — separate credentials per account | Yes — one login, all accounts |
| Terraform workflow | Keys in file, just works (dangerously) | aws sso login then terraform |
7. What's Next
This setup is the foundation. From here the natural next topics are:
- Multiple AWS accounts — separate accounts for dev, staging, prod under the same Organization. Same SSO login, different permission sets per account.
- Scoped permission sets — instead of
AdministratorAccesseverywhere, create aTerraformDeployset with only what Terraform actually needs. Use IAM Access Analyzer to discover what was actually used. - CI/CD with zero credentials — for GitHub Actions, use OIDC federation. No static keys in your pipeline either.
- External identity provider — connect IAM Identity Center to Okta, Google Workspace, or Azure AD. Users log in with company credentials, AWS access follows automatically.
- Service Control Policies — organisation-level guardrails. Even admins cannot exceed them. The right tool for enforcing region restrictions, mandatory tagging, or blocking risky services.