← AWS labs IAM and OIDC · Days 40 to 43

AWS labs · Lesson 2 · IAM and OIDC

Who are you, and what may you do?

IAM, OIDC, OAuth, SAML, STS, JWT, SSO, IRSA… it sounds like a pile of acronyms, but they all fit one story. Something wants to use AWS. First it has to prove who it is with a proof AWS trusts. Then AWS swaps that proof for short-lived keys. Then every request is checked against policies. Learn that story once and every name below has an obvious place in it.

The whole of AWS access in four sentences
  1. Every request to AWS answers two questions: who are you? (authentication) and what may you do? (authorization).
  2. "Who" is proven by someone AWS already trusts: GitHub or an EKS cluster with an OIDC token, your company login with SAML, or AWS itself for an EC2 machine.
  3. STS swaps that proof for temporary keys of a role. The role's trust policy decides who may borrow it.
  4. The role's permission policies decide what it can do. An explicit Deny anywhere wins, and nothing is allowed unless something allows it.

01 Every name on one map

Each name answers one of three questions. Read left to right: that's also the order things happen in.

Prove who you are

authentication
OIDC (OpenID Connect)A standard way for a trusted party to say "this is who this is" with a signed token. Built on OAuth 2.0.GitHub Actions, EKS pods, "Log in with Google"
JWT (JSON Web Token)The token OIDC hands out: three parts, readable by anyone, signed so nobody can change it.the "ID card" itself
SAMLThe older single sign-on standard. Same job as OIDC, but an XML document instead of a JWT.company login into AWS, Salesforce…
OAuth 2.0About access, not identity: lets an app act for you on another service without your password."allow this app to read your repos"
Identity provider (IdP)Whoever vouches for you and signs the proof.GitHub, an EKS cluster, Entra ID, Okta, Google
SCIMKeeps user lists in sync from the identity provider to apps, so leaving the company removes access everywhere.Entra ID → IAM Identity Center
MFAA second proof (phone, key) on top of the password, checked by the identity provider.

Swap the proof for keys

AWS takes over
IAM identity providerYour account's record that says "I trust tokens from this OIDC issuer" or "from this SAML provider".token.actions.githubusercontent.com
STS (Security Token Service)The desk that checks the proof and hands out temporary keys for a role.AssumeRole · AssumeRoleWithWebIdentity · AssumeRoleWithSAML
RoleA set of permissions that someone or something borrows for a while. No password, no permanent keys.arn:aws:iam::111122223333:role/deploy-web
Trust policyAttached to a role: who may borrow it, and on what conditions (which repo, which service account).
Temporary credentialsAccess key (starts ASIA), secret and session token, valid for minutes to hours.long-lived IAM user keys start AKIA
IAM Identity CenterAWS's single sign-on for people: log in with the company account, pick an AWS account and a permission set.
Instance profile, IRSA, Pod IdentityHow machines inside AWS get a role: an EC2 instance, or a Kubernetes pod.

Decide what you may do

authorization
Permission policyJSON that allows or denies actions on resources. Attached to a role, user or group (identity policy).Allow s3:PutObject on acme-web-site/*
Resource policyA policy attached to the thing itself, like an S3 bucket policy. It names who may use it.
SCP (service control policy)A ceiling for a whole account, set by AWS Organizations. Can only take permissions away.
Permission boundaryA ceiling for one role or user. Also only takes away.
Session policyAn extra ceiling passed when a role is assumed, for that one session.
ARN and conditionsHow policies name things (arn:aws:s3:::bucket) and add rules like "only from this repo" or "only with MFA".
identity provider signs a proof→STS checks it + the role's trust policy→temporary keys→each request checked against policies→allowed or denied

02 The token journey, in 3D

Four everyday situations, one machinery. Step through each and watch what travels between whom. Notice that STS, the role and the bucket never change: only the proof of identity does.

Try it. Pick a scenario, then use Next (or the arrow keys) to move the token one hop at a time. Drag to turn the scene; open it on its own to zoom. Colours: proof of identity, keys from STS, a check by IAM, the real call you wanted.

SituationWho vouchesProofSTS callTrust policy trusts
GitHub Actions deploysGitHubOIDC token (JWT)AssumeRoleWithWebIdentitythe GitHub OIDC provider, for one repo and branch
EC2 machine reads S3AWS itselfbeing that instancedone for you via the metadata servicethe service ec2.amazonaws.com
Pod in EKS reads S3the EKS clusterOIDC token (JWT)AssumeRoleWithWebIdentitythe cluster's OIDC provider, for one service account
You log in to the consoleCompany login (Entra, Okta)SAML assertionAssumeRoleWithSAML (by Identity Center)Identity Center's SAML provider

03 Inside a token

This is the kind of token GitHub gives a CI job. A JWT is three parts separated by dots. The first two are just base64: anyone can read them. The third is a signature only GitHub can make, so nobody can change a single character without being caught.

1 · Header

which key and algorithm signed it

2 · Payload (claims)

who this is, for whom, until when

3 · Signature

made with GitHub's private key; checked with its public key
ClaimMeansWhy AWS cares
issIssuer: who signed itMust match an OIDC identity provider registered in your account
audAudience: who it's meant forShould be sts.amazonaws.com, so a token meant for another service can't be replayed at AWS
subSubject: exactly who this isThe trust policy pins it, e.g. repo:acme/web:ref:refs/heads/main
exp, iat, nbfExpiry, issued at, not beforeOld tokens are refused; GitHub's live for minutes
repository, ref, environment, job_workflow_refExtra GitHub detailsCan be used in conditions too, for finer rules
Readable is not secretBase64 is an encoding, not encryption. Never put secrets in a JWT, and treat a valid token like a key while it lasts: whoever holds it can use it until it expires.

04 OAuth, OIDC and SAML, side by side

Three standards that people mix up. OAuth is a valet key: it lets something do a job for you. OIDC and SAML are ID badges: they say who you are.

OAuth 2.0OIDCSAML 2.0
AnswersWhat may this app do for you?Who is this?Who is this?
Gives youan access token, to call an APIan ID token (always a JWT), plus OAuth's access tokenan assertion (signed XML)
Since20122014, built on top of OAuth 2.02005
Typical use"Allow this app to read your calendar""Log in with Google", machine-to-cloud (GitHub → AWS, EKS → AWS)company single sign-on into business apps
In AWSaws sso login uses an OAuth device flowIAM OIDC identity providers, AssumeRoleWithWebIdentityIAM SAML providers, Identity Center, AssumeRoleWithSAML
How trust is checkedthe API checks the access tokensignature checked against the issuer's public keys (JWKS), found via /.well-known/openid-configurationsignature checked against the provider's certificate from its metadata file
Rule of thumbMachines talking to AWS today: OIDC. People logging in through the company: SAML (often hidden behind Identity Center). An app acting on your behalf somewhere: OAuth.

05 IAM building blocks

Four nouns, and one shape of policy. This is roadmap Day 40.

User
A long-lived identity with a password and/or access keys. Fine for a quick lab; avoid for real people (use Identity Center) and for machines (use roles).
Group
A bag of users that share policies. Policies attach to the group, people join and leave.
Role
Permissions with no owner, borrowed for a session. What machines, CI jobs, other accounts and SSO users actually use.
Policy
A JSON document of Effect (Allow or Deny), Action (what), Resource (on what) and optional Condition (only when…). Resource policies also name a Principal (who).

The confusion everyone has: a role has two policies

Trust policy: who may borrow this role?

The Principal is the GitHub OIDC provider; the conditions pin the audience and exactly one repo and branch.

Permission policy: what can the role do?

Only uploads into one bucket. Least privilege: no s3:*, no "Resource": "*".

Identity policy vs resource policyAn identity policy is attached to a user, group or role and says what they can do. A resource policy is attached to a bucket, queue or key and says who may use it. In one account, either one allowing is usually enough (unless something denies; KMS keys are the main exception). Across accounts, both sides must allow.

06 Trust-policy checker

The trust policy above only lets the main branch of acme/web deploy. Change what the token says and see which condition stops it.

Token sub:

    Why the strict line mattersGitHub signs tokens for every repo on GitHub. If the sub condition is * or missing, anyone who can run a workflow anywhere can assume your role. Pin the repo, and pin the branch or environment for anything that deploys.

    07 Is this request allowed?

    Once a role has keys, every single request is evaluated against every policy that applies. Set what each layer says and watch the decision. The rule: an explicit Deny anywhere wins; otherwise every ceiling must allow, and at least one grant must allow.

      This is the same-account logic. Across two accounts, the caller's own policies and the resource's policy must both allow.

      08 Hear a problem, pick a pattern

      The same few patterns cover almost every request you'll hear. The first question is always: is it a person, a machine inside AWS, or something outside AWS?

      09 Traps

      TrapWhy it hurtsDo this instead
      Access keys (AKIA…) in code, a laptop file or a CI secretThey never expire and leak through logs, screenshots and old commitsRoles everywhere: OIDC for CI, instance profiles and IRSA for apps, aws sso login for people
      A trust policy with sub as * or a whole orgAny repo (or anyone on GitHub) can assume the rolePin repo:org/name plus the branch or environment
      Forgetting the aud conditionA token meant for another service could be replayed at AWSRequire aud = sts.amazonaws.com
      Using the root userIt can't be limited by any policyMFA on root, lock it away, use it only for the few root-only tasks (Day 37)
      "Action": "*" and "Resource": "*"One leaked role can do anythingName the actions and resources; start small and add what's missing
      Fixing an AccessDenied by attaching AdministratorAccessHides the real cause and leaves a holeRead the error: it names the action and resource; check SCPs, boundaries and denies (Day 43)
      Leaving IMDSv1 on EC2A web bug can trick the app into fetching the instance's keysRequire IMDSv2 (session tokens) on every instance

      10 Self-check

      Ten questions. The reason appears after you choose.

      Glossary

      Authentication
      Proving who you are.
      Authorization
      Deciding what you may do.
      Principal
      Whoever is making the request: a user, a role session, an AWS service, a federated identity.
      Federation
      Trusting identities from outside AWS (GitHub, Entra ID, Okta) instead of creating IAM users.
      JWKS
      JSON Web Key Set: the public keys an OIDC issuer publishes so anyone can check its signatures.
      Claim
      One field inside a token, like sub or aud.
      Assume a role
      Exchange a proof for temporary credentials of that role.
      Permission set
      In Identity Center, a reusable bundle of policies that becomes a role in each account it's assigned to.
      External ID
      A shared secret a third-party service must send when assuming a role in your account, so other customers of that service can't.
      Least privilege
      Give only the permissions a job needs, nothing more.

      Use this in the roadmap

      IAM and OIDC · AWS labs Example names (acme, 111122223333) are made up