Understanding the Different Ways to Access AWS
For someone learning AWS cloud, it is often hard to understand how to get access to an AWS environment and what options exist. Identity is fundamental to security, and this blog demystifies the different access methods. There may be other patterns out there, but this should give you a good foundation.
IAM User Access Keys (Legacy, Avoid)
Long-lived access key ID + secret access key stored in
~/.aws/credentials or environment variables. Never expires
unless you rotate manually.
When used:
- Legacy applications that haven’t been migrated
- Quick local development (bad habit)
- Third-party tools that only support static keys
Example: Developer has
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in
their shell profile. Runs aws s3 ls from their laptop.
Why to avoid: Keys don’t expire. If leaked (git commit, logs, stolen laptop), attacker has permanent access until you notice and revoke. No MFA enforcement on API calls. Rotation is manual and painful.
Better alternative: Use Identity Center (SSO) for humans, IAM roles for workloads. If you have existing access keys, figure out how to discover them and move to other secure options.
IAM Role via Instance Profile (Workloads in AWS)
AWS automatically provides temporary credentials to workloads running inside AWS. No keys to manage. Credentials rotate automatically every few hours.
When used:
- EC2 instances calling AWS services
- ECS/Fargate tasks
- Lambda functions
- Any compute running inside AWS
Example: An EC2 instance has an instance profile
attached with a role that allows S3 access. The application calls
aws s3 cp and it automatically gets credentials from the
instance metadata service (169.254.169.254). No configuration
needed.
Why this is the gold standard: Zero credential management. Automatic rotation. Can’t accidentally leak keys that don’t exist. Scoped to the role’s permissions.
How it works under the hood: AWS STS generates short-lived credentials and injects them into the instance metadata service (EC2), environment variables (Lambda), or task role (ECS). SDKs pick them up automatically.
IAM Identity Center (SSO for Employees)
Employees authenticate with their corporate identity provider (Okta, Azure AD, Google Workspace) and get temporary AWS credentials for specific accounts and permission sets. Replaces IAM users for human access.
When used:
- Employees accessing AWS Console
- Developers using AWS CLI (
aws sso login) - Teams managing multiple AWS accounts
- Anyone who needs “which account do I want to work in today?”
Example: Developer runs aws sso login.
Browser opens, they authenticate with Okta. Identity Center maps their
Okta group to a Permission Set (e.g., “DeveloperAccess” in the dev
account). They get temporary credentials valid for 1-12 hours.
The flow:
- Employee authenticates with corporate IdP (MFA enforced)
- IdP sends SAML assertion to Identity Center
- Identity Center maps user/group to Permission Set + Account
- STS generates temporary credentials
- Employee gets credentials for the specific account
Why use this over IAM users:
- No passwords stored in AWS
- MFA handled by corporate IdP
- Centralized access management (add/remove in IdP, not per-account)
- One login gives access to multiple accounts
- Credentials expire automatically
STS AssumeRole (Already Have Creds, Need Different Ones)
You already have AWS credentials (from any method above) and want to switch to a different role, usually in another account or with different permissions.
When used:
- Cross-account access (tooling account to production account)
- Privilege escalation (normal role to admin role for specific task)
- Service-to-service within AWS (Lambda assumes a role to access another account’s resources)
- Chaining: Role A assumes Role B assumes Role C
Example: CI/CD pipeline runs in a tooling account. It assumes a deployment role in the production account to push code. The trust policy on the production role says “only the tooling account’s pipeline role can assume me.”
Key point: This isn’t how you get your FIRST credentials. It’s how you exchange existing credentials for different ones.
OIDC Federation (AssumeRoleWithWebIdentity)
A machine or system authenticates with an OIDC-compatible identity provider and exchanges the OIDC token for AWS credentials. No AWS credentials stored in the external system.
When used:
- GitHub Actions to AWS (most common modern use case)
- GitLab CI to AWS
- Kubernetes pods (EKS IRSA, pod gets OIDC token, exchanges for AWS role)
- Mobile apps authenticating via Google/Apple/Facebook
- Any CI/CD system that supports OIDC
Example: GitHub Actions workflow needs to deploy to AWS. No access keys stored in GitHub secrets. Instead, GitHub issues an OIDC token proving “this is repo X, branch main, workflow deploy.yml.” AWS trust policy validates the token and issues temporary credentials.
The flow:
- GitHub Actions requests OIDC token from GitHub’s OIDC provider
- GitHub returns a signed JWT with claims (repo, branch, workflow)
- Workflow calls AssumeRoleWithWebIdentity with the JWT
- AWS validates JWT signature and checks claims against trust policy
- STS returns temporary credentials
- Workflow deploys to AWS
Why this is better than access keys in CI/CD:
- No long-lived secrets to store or rotate
- Trust policy can restrict by repo, branch, environment (e.g., only
mainbranch can deploy to prod) - Credentials last minutes, not forever
- If GitHub is compromised, attacker still needs to match the trust policy conditions
SAML Federation (AssumeRoleWithSAML)
Enterprise SSO using SAML 2.0. User authenticates with corporate IdP, gets a SAML assertion, exchanges it for AWS credentials. Older protocol than OIDC but still widely used.
When used:
- Enterprise SSO to AWS Console (before Identity Center existed)
- Organizations using ADFS, Okta, Ping, OneLogin with SAML
- Legacy federation setups that predate Identity Center
Example: Employee clicks “AWS” in their Okta dashboard. Okta sends a SAML assertion to AWS. AWS maps the SAML attributes (groups) to an IAM role. Employee lands in the Console with that role’s permissions.
Identity Center vs SAML Federation:
- Identity Center is the modern replacement, easier to manage, supports multiple accounts natively, has a CLI experience
- SAML federation still works and is common in orgs that set it up years ago
- New setups should use Identity Center
Cognito (App End-Users to AWS Credentials)
Two-step process for giving your application’s end-users (customers, not employees) scoped AWS credentials. User Pool handles authentication. Identity Pool exchanges the token for IAM credentials.
When used:
- Mobile app users uploading photos directly to S3
- Web app users accessing DynamoDB from the browser
- IoT devices that need per-device AWS credentials
- Any scenario where end-users need direct AWS API access (not through your backend)
Example: User signs into your mobile app with
email/password. App gets a JWT from Cognito User Pool. App exchanges
that JWT with Cognito Identity Pool for temporary AWS credentials scoped
to only their S3 prefix (s3://bucket/users/{userId}/*).
User Pool vs Identity Pool:
- User Pool is authentication (who are you?). Manages users, passwords, MFA, social login. Issues JWTs.
- Identity Pool is credential vending (give me AWS creds). Exchanges tokens for IAM credentials. Maps authenticated/unauthenticated users to IAM roles.
Why not just use your backend as a proxy? Direct S3 upload from mobile means no bandwidth through your servers. Scales infinitely (S3 handles the load, not your API). Lower latency for end users. But only makes sense when users need direct AWS access. Most apps just use backend APIs.
IAM Roles Anywhere (Workloads Outside AWS)
On-prem servers, Azure VMs, GCP instances, or any workload outside AWS gets temporary credentials by presenting an X.509 certificate. Same automatic credential experience as EC2 instance profiles, but for non-AWS compute.
When used:
- On-prem servers that need to call AWS APIs (S3 backup, DynamoDB sync)
- Azure/GCP workloads accessing AWS services
- Edge devices or IoT gateways
- Any non-AWS compute that previously used long-lived access keys
Example: On-prem backup server has a certificate issued by your private CA. It calls IAM Roles Anywhere, presents the certificate. AWS validates it against your registered Trust Anchor (CA). Returns temporary credentials. Server backs up to S3.
Why this over access keys for on-prem:
- Credentials are temporary (expire in hours, not never)
- Certificate rotation is standard PKI practice (already have tooling)
- If certificate is compromised, revoke it via CRL, immediate effect
- Audit trail shows which certificate was used
- No secrets to store in config files
Setup requirements: A private CA (AWS Private CA or your own), Trust Anchor registered in IAM Roles Anywhere (your CA’s root cert), Profile mapping certificate attributes to an IAM role, Certificate installed on the on-prem server.
Quick Decision Matrix
| Situation | Method | Why |
|---|---|---|
| EC2/ECS/Lambda needs AWS access | Instance Profile | Automatic, zero management |
| Employee needs Console/CLI | Identity Center | SSO, MFA, multi-account |
| CI/CD pipeline (GitHub, GitLab) | OIDC Federation | No stored secrets, scoped by repo/branch |
| Cross-account access | AssumeRole | Exchange existing creds for target role |
| On-prem server needs AWS access | Roles Anywhere | Temp creds via certificate, no access keys |
| Mobile app user uploads to S3 | Cognito | Per-user scoped creds, direct to AWS |
| Legacy app, can’t change | IAM User keys | Last resort. Rotate frequently. |
| Enterprise SSO (existing SAML) | SAML Federation | Works, but migrate to Identity Center |
| Azure/GCP workload to AWS | Roles Anywhere or OIDC | Certificate or OIDC token exchange |
The Key Principle
Never store long-lived credentials if you can avoid it. Every method above (except Method 1) produces temporary credentials that expire. The identity proof (certificate, OIDC token, SAML assertion, metadata service) is the starting point, AWS always converts it to short-lived STS credentials.
If you remember one thing from this post: the credential is never the identity. The identity is proven somewhere else (your IdP, your CA, the metadata service), and AWS just converts that proof into temporary access.