SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Identity and Access Management

AWS Authentication Strategies: MFA, STS, and Federation

28 min readSCS-C03 · Identity and Access ManagementUpdated

Authentication on AWS is the discipline of proving who a principal is and issuing it credentials — ideally short-lived ones minted by AWS STS rather than static access keys. Task 4.1 of the SCS-C03 exam covers three skills: designing identity solutions for human, application, and system authentication (IAM Identity Center, Amazon Cognito, MFA, and identity provider integration); configuring the mechanisms that issue temporary credentials (AWS STS and Amazon S3 presigned URLs); and troubleshooting authentication with evidence from CloudTrail, Cognito, Identity Center permission sets, and AWS Directory Service. This lesson works through each: how MFA is enforced and which factors resist phishing, how each STS API behaves and what its credentials can and cannot do, how session duration, session tags and source identity travel, how workforce federation and workload federation are wired, and how to read the failures when any of it breaks. Two neighbouring topics are deliberately left to their own lessons: root user credentials and centralized root access belong to Task 6.1 (AWS Organizations and multi-account security), and session policies and other permission ceilings belong to Task 4.2 (IAM policy evaluation and authorization).

What you’ll learn
  • Enforce MFA with deny-based policies, let users self-enroll a device, and choose phishing-resistant factors
  • Choose the correct AWS STS API for each caller and explain what GetSessionToken, GetFederationToken and AssumeRole credentials can and cannot do
  • Control session duration, role chaining, session tags and source identity across federation and role chains
  • Design trust policies that defeat the confused deputy with a vendor-generated external ID
  • Integrate IAM Identity Center and direct SAML federation with external IdPs and AWS Directory Service, including MFA and SCIM provisioning
  • Authenticate workloads with OIDC federation, EKS Pod Identity or IRSA, instance profiles, IAM Roles Anywhere, Amazon Cognito and S3 presigned URLs
  • Troubleshoot STS errors, SAML and OIDC federation failures, Identity Center provisioning, directory connectivity and Cognito token problems using CloudTrail

Strong authentication baselines: MFA everywhere

MFA on AWS is enforced by policy, and its strength depends on the factor you choose. IAM supports three factor types for IAM users and the root user: FIDO2 security keys and passkeys, virtual authenticator apps (TOTP), and hardware TOTP tokens. SMS is not an IAM MFA option. Each IAM user can register up to eight MFA devices of any mix of supported types, which is how you give an administrator a backup.

FactorHow it proves presenceReal-time phishing proxy
FIDO2 security key or passkeySigns a challenge bound to the sign-in originResists it: a lookalike domain gets a signature that AWS will not accept
Virtual authenticator app (TOTP)User types a six-digit codeVulnerable: the proxy relays the typed code within its validity window
Hardware TOTP tokenUser types a code from a key fob or cardVulnerable for the same reason — the code is typed, so it can be relayed

The distinction that matters is not hardware versus software but origin-bound signature versus typed code: any factor whose output a person types can be captured and replayed by a proxy page, so privileged users get FIDO2.

Enforcing MFA with an explicit deny

The standard pattern is an identity-based (or guardrail) deny that blocks everything when the request carries no MFA, with the enrollment actions carved out inside the same statement using NotAction:

{
  "Sid": "DenyAllExceptMfaSetupWithoutMfa",
  "Effect": "Deny",
  "NotAction": [
    "iam:CreateVirtualMFADevice",
    "iam:EnableMFADevice",
    "iam:GetUser",
    "iam:ListMFADevices",
    "iam:ResyncMFADevice",
    "sts:GetSessionToken"
  ],
  "Resource": "*",
  "Condition": {
    "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" }
  }
}

The carve-out has to live in the deny. Policy evaluation lets an explicit deny override every allow, so a separate Allow statement for iam:EnableMFADevice cannot rescue a user caught by a deny on "Action": "*". The companion Allow statements then grant the self-service actions on the right resources: iam:CreateVirtualMFADevice targets an MFA device ARN (arn:aws:iam::*:mfa/*), while iam:EnableMFADevice, iam:ListMFADevices and iam:ResyncMFADevice target the user's own ARN (arn:aws:iam::*:user/${aws:username}). After enrolling, the user must sign out and back in: the session they enrolled from was authenticated without MFA and stays that way.

Choosing the condition operator

Condition in the denyLong-term access key request (key absent)Session without MFASession with MFA
Bool aws:MultiFactorAuthPresent = falseNot denied — a missing key never matches BoolDeniedAllowed
BoolIfExists aws:MultiFactorAuthPresent = falseDenied — IfExists treats a missing key as a matchDeniedAllowed
Null aws:MultiFactorAuthAge = trueDenied — the age key exists only when MFA was usedDeniedAllowed

aws:MultiFactorAuthPresent is never present on requests signed with long-term access keys, which is why plain Bool silently exempts them. aws:MultiFactorAuthAge holds the number of seconds since MFA authentication and is likewise absent for long-term keys; to force recent MFA for sensitive actions, deny with NumericGreaterThanIfExists on the age (for example 3600) so key-signed requests are also caught.

Keeping devices working

ResyncMFADevice needs two consecutive codes generated by the device itself. It fixes a TOTP device whose clock has drifted, but it cannot recover a lost device — the recovery path is a second registered device, or an administrator deactivating the lost one.

Credential hygiene: eliminating long-term keys

The strongest credential strategy is to have as few long-term credentials as possible. Every place an access key lives — a developer laptop, a CI runner, an EC2 user-data script — is a place it can leak, and a leaked key is valid until someone notices. The design answer is roles everywhere: humans federate through IAM Identity Center, applications use instance profiles, task roles, or OIDC federation, and servers outside AWS use IAM Roles Anywhere. (Root user credentials are their own problem, handled organization-wide with centralized root access management in the Task 6.1 lesson.) Temporary credentials expire on their own; revocation is a property of the design rather than an incident-response scramble.

For the keys you cannot yet eliminate, the exam expects you to know the audit tooling by name. The IAM credential report is a downloadable, account-wide CSV listing every user with the age and status of their passwords, access keys, and MFA devices — the fastest way to answer "which users still have keys older than 90 days?". Access key last used data (visible in the console and via GetAccessKeyLastUsed) tells you whether a key is actually in use before you deactivate it. IAM access advisor (service last accessed data) shows which services a user or role actually called, which drives least-privilege pruning — but note that is an authorization concern that Task 4.2 picks up. Where rotation is unavoidable, follow the two-key dance: create the second key, deploy it, confirm the old key shows no recent use, deactivate it, observe, then delete. Deactivation is reversible; deletion is not — the exam rewards the sequence that never causes an outage.

STS in depth: choosing the right API

AWS STS is the mint for temporary credentials, and each API exists for a different kind of caller. The credentials they return are not interchangeable: some cannot call IAM, some cannot call STS again, and only some carry MFA context.

APICallerTypical use
AssumeRoleAny principal holding AWS credentialsCross-account access, privilege switching, workload roles, third-party access with external ID; MFA can be supplied with SerialNumber + TokenCode
AssumeRoleWithSAMLAnyone holding a SAML 2.0 assertion from a trusted IdPDirect workforce federation to IAM roles without existing AWS credentials
AssumeRoleWithWebIdentityAnyone holding an OIDC token from a trusted providerCI pipelines, EKS IRSA, Cognito basic flow
GetSessionTokenAn IAM user (or root) with long-term keysMinting an MFA-bearing session from access keys
GetFederationTokenAn IAM user acting as a custom identity brokerLegacy broker issuing scoped credentials for a named federated user

What GetSessionToken and GetFederationToken credentials can do

GetSessionTokenGetFederationToken
PermissionsThe calling IAM user's own permissionsIntersection of the IAM user's permissions and the session policy passed in the call; no session policy means no permissions
Session policyNot acceptedAccepted (with a required Name for the federated user)
MFAAccepts an MFA code, so the session carries MFA contextCannot carry MFA context
IAM API callsOnly if MFA was suppliedNone through the API or CLI
STS API callsOnly AssumeRole and GetCallerIdentityOnly GetCallerIdentity — so it cannot assume a role
Console sign-in via federation endpointNoYes
Duration15 minutes to 36 hours (default 12 hours); root at most 1 hour15 minutes to 36 hours (default 12 hours); root at most 1 hour

Two consequences follow. A user with long-term keys who must satisfy an MFA condition gets the MFA context from GetSessionToken (or from AssumeRole with an MFA code) — never from GetFederationToken. And a broker that needs role credentials cannot obtain them from a federation-token session, because that session cannot call AssumeRole.

On the command line, the mfa_serial setting in a profile takes effect when that profile also names a role_arn: the CLI prompts for the code and passes it on the AssumeRole call. A profile with only access keys and mfa_serial does not prompt; it needs an explicit aws sts get-session-token --serial-number … --token-code ….

Session duration, role chaining, session tags, and source identity

A temporary session's lifetime is set by the API that minted it and capped by the role it represents, and anything attached to the session at creation — tags, source identity — travels with it.

Duration and role chaining

  • Role maximum session duration is configured per role between 1 and 12 hours (default 1 hour). AssumeRole, AssumeRoleWithSAML (through the SAML SessionDuration attribute) and AssumeRoleWithWebIdentity can request up to that maximum; asking for more fails.
  • Role chaining — using role-session credentials to assume another role — is limited to one hour. A chained AssumeRole that requests more than 3,600 seconds fails; it is not quietly shortened. A longer session requires a first-hop assumption from a non-role identity (an IAM user, a federated sign-in or a workload credential source).
  • EC2 instance profile credentials are themselves a role session, so an application on EC2 that assumes a second role is chaining and is held to one hour. Long-running work stays authorized through automatic refresh: the SDK's assume-role credential provider re-assumes the role before each session expires.
  • GetSessionToken and GetFederationToken run from 15 minutes to 36 hours for an IAM user and at most 1 hour for root. Both start from an IAM user's long-term access key, which is why role sessions are preferred where a role can be used.

Session tags

Session tags are key-value pairs attached when the session is created, from an AssumeRole parameter, a SAML attribute (https://aws.amazon.com/SAML/Attributes/PrincipalTag:{TagKey}) or an OIDC claim. They appear to policies as aws:PrincipalTag/{TagKey} and drive ABAC. Three rules govern them:

  • The role's trust policy must allow sts:TagSession. When an IdP passes tags, every role reachable through that IdP needs it, or sign-in to that role fails; if some roles cannot be changed, use a separate IdP configuration that does not send tags.
  • Tags live on the session, not the role: nothing is written to the role, and a new session gets only the tags passed for it.
  • Tags named in TransitiveTagKeys (SAML attribute https://aws.amazon.com/SAML/Attributes/TransitiveTagKeys) persist through role chaining, and a later hop that tries to set a different value for a transitive tag fails.

Source identity

Source identity records who started a session — typically the human's user name — and, unlike the role session name or session tags, it is set once and cannot be changed for the rest of the chain. It is supplied by the SourceIdentity SAML attribute, the SourceIdentity parameter of AssumeRole, or an OIDC claim; the role's trust policy must allow sts:SetSourceIdentity. It persists through role chaining and appears in the session context of every CloudTrail event, so an action taken three roles deep is still attributable to the person who began the chain.

AttributeWho sets itChanges during a chain?Main use
Role session nameThe caller, per AssumeRole callYes — each hop chooses its ownLabels one session in CloudTrail and the assumed-role ARN
Session tagsCaller or IdP, per sessionYes, except transitive tagsABAC via aws:PrincipalTag
Source identityCaller or IdP, onceNo — immutableAttributing every action in the chain to the original identity

Session policies, which narrow a session's permissions at assume time, are an authorization ceiling and are taught with the rest of policy evaluation in the Task 4.2 lesson.

Trust policies and the external ID defense: a worked scenario

A role has two policy halves: the permissions policy (what the session can do — Task 4.2) and the trust policy (who may become the role). The trust policy is a resource-based policy whose Principal names the trusted account, role, service, or federated provider, and whose Condition block is where authentication controls live: sts:ExternalId for third parties, aws:MultiFactorAuthPresent to require that the assuming identity carries MFA, source conditions for service principals. (Designing trust policies as authorization controls — who should be trusted at all — is covered in the Task 4.2 lesson; here the focus is the authentication checks they perform.)

Walk the classic scenario. A monitoring vendor operates from its own AWS account and needs read access to your account, and to hundreds of other customers' accounts. You create a role trusting the vendor's account. The danger is the confused deputy: a malicious customer of the same vendor, knowing or guessing your role's ARN, asks the vendor's platform to connect to your role. The vendor — a deputy acting with its own credentials, which your trust policy accepts — would succeed. The defense is an external ID. Your trust policy requires a value the vendor gives you:

"Condition": {
  "StringEquals": { "sts:ExternalId": "vendor-generated-id-for-your-account" }
}

The protection depends on who generates the value. The vendor generates a unique external ID for each customer, stores it with that customer's record, passes it on every AssumeRole call made for that customer, and never lets customers choose or edit it. The attacker can enter your role ARN, but the vendor attaches the attacker's own external ID, the StringEquals fails, and STS returns AccessDenied. If customers could pick the value, the attacker could simply type yours and the binding would be gone. The external ID is not a secret credential; it binds the vendor's customer record to your role.

Other conditions do not solve this problem. aws:PrincipalAccount, the vendor's role ARN or the vendor's source IP range all identify the vendor — and in a confused-deputy request the vendor is the caller, so the attacker's request passes them. Only a per-customer value that the vendor supplies separates one customer's request from another's.

Trust policies bind to unique IDs

When a trust policy (or any resource-based policy) names an IAM role or user, IAM stores that principal's unique ID behind the ARN. If the principal is deleted, the policy shows an ID beginning AROA (role) or AIDA (user) in place of the ARN, and a newly created principal with the same name does not match — it is a different principal. Re-enter the ARN in the policy to trust the new one. This is a security feature: recreating a deleted name cannot inherit its access.

Workforce federation: IAM Identity Center vs direct SAML

IAM Identity Center is AWS's recommended workforce answer for multi-account organizations. Its unit of authorization is the permission set — a template that Identity Center provisions as an IAM role (named AWSReservedSSO_…) in every account where a user or group is assigned. Assign one group a ReadOnly permission set across 40 accounts and Identity Center provisions and maintains 40 roles; users sign in once to the access portal and receive short-lived credentials in each account. The AWSReservedSSO_ roles belong to Identity Center: change the permission set, never the role.

Direct SAML 2.0 federation to IAM predates Identity Center. You create a SAML identity provider in IAM, create roles that trust it, and the IdP's assertion carries a Role attribute listing role-ARN/provider-ARN pairs; the sign-in endpoint then calls AssumeRoleWithSAML. An IAM SAML provider exists in one account only and cannot be shared (not through AWS RAM either), so federating directly into many accounts means a provider in each account, with each Role value pairing a role with the provider in that role's account. That per-account sprawl is the main reason Identity Center is the default at scale.

IAM Identity CenterDirect SAML to IAM
ScopeEvery account in the organization from one placeOne IAM SAML provider and set of roles per account
Authorization unitPermission set assigned to users/groups per accountIAM roles, chosen through the assertion's Role attribute
User lifecycleSCIM provisioning (external IdP) or directory syncNone in AWS — access follows what the IdP asserts
FitsWorkforce access across an organizationA single account, legacy integrations, or brokers that call STS themselves

Workforce identities need MFA wherever they authenticate: at the external IdP when one is connected, or in Identity Center's own MFA settings when Identity Center or Active Directory is the identity source (next section).

IAM Identity Center identity sources, MFA, and SCIM provisioning

IAM Identity Center authenticates users against exactly one identity source at a time, and the source decides where users live, how they are provisioned and where MFA is enforced.

Identity sourceUsers and groups come fromMFA configured in
Identity Center directoryCreated in Identity CenterIdentity Center MFA settings
Active Directory (AWS Managed Microsoft AD, or self-managed AD through AD Connector)Synced from the directoryIdentity Center MFA settings (or a RADIUS MFA on the directory)
External IdP (Entra ID, Okta, others) over SAML 2.0Provisioned by SCIM, or created manually with matching user namesThe external IdP — Identity Center's MFA settings are not available

External IdP: SAML for sign-in, SCIM for provisioning

With an external IdP, SAML authenticates the user, but the user must already exist in Identity Center: there is no just-in-time creation at first sign-in. SCIM automates that — creating, updating and deleting users and group memberships as the IdP changes, so disabling someone at the IdP removes their AWS access. Identity Center issues the SCIM access token the IdP uses, and it is valid for one year. When it expires, provisioning stops without any sign-in error: new hires never appear and leavers are never removed, while existing users keep signing in through SAML. Identity Center shows the expiry date in the console and sends expiry notifications, but nothing else fails, so track the expiry and rotate the token before it lapses.

MFA when Identity Center or AD is the source

Identity Center's MFA settings have three parts. The prompt mode is every sign-in (always-on) or only when the sign-in context changes (context-aware), or MFA can be disabled. The allowed MFA types are security keys and built-in authenticators (FIDO2/WebAuthn, including passkeys and platform authenticators) and authenticator apps (TOTP). The no-device behaviour decides what happens to a user without a registered device: require registration at sign-in, send a one-time password by email, block sign-in, or allow sign-in without MFA.

AWS Directory Service as the source

AD ConnectorAWS Managed Microsoft AD
What it isA proxy that forwards authentication to your on-premises AD; nothing is cached or stored in AWSA real AD domain run by AWS
DomainsOne domainMultiple domains and forests through trusts
Identity Center requirementNetwork reachability to the domain controllers and a working service accountTo reach users in an on-premises forest, a two-way forest trust — a one-way trust does not work
Typical breakThe service account's password changes in AD but not in Directory ServiceTrust broken or one-way; DNS or network path to the on-premises forest

Simple AD is not a supported Identity Center identity source, and SCIM applies only to external IdPs — directory sources sync through the directory connection.

Workload identity: CI pipelines, EKS, EC2, and servers outside AWS

Workloads should authenticate with credentials that are issued to them and expire, never with stored access keys. The mechanism depends on where the workload runs.

CI pipelines: OIDC federation

A GitHub Actions job presents a short-lived OIDC token to AssumeRoleWithWebIdentity. The account has an IAM OIDC provider for token.actions.githubusercontent.com, and the role's trust policy conditions on two claims: aud, which is sts.amazonaws.com for the official AWS credentials action, and sub, which identifies the repository and context. IAM rejects a trust policy for the GitHub provider whose sub condition is missing or is only a wildcard, because that would let any repository on GitHub assume the role.

Job contextsub claim
Push to a branchrepo:<org>/<repo>:ref:refs/heads/<branch>
Job that references a GitHub environmentrepo:<org>/<repo>:environment:<name> — replaces the ref form
Pull requestrepo:<org>/<repo>:pull_request
Any context in one repositoryrepo:<org>/<repo>:* with StringLike

Because an environment job's sub carries the environment instead of the branch, a trust policy written for a branch will not match a job that uses an environment.

Amazon EKS: IRSA versus EKS Pod Identity

IAM roles for service accounts (IRSA)EKS Pod Identity
MechanismPer-cluster IAM OIDC provider; pod calls AssumeRoleWithWebIdentityPod Identity Agent on the node exchanges the pod's token; trust policy principal pods.eks.amazonaws.com
Trust policyNames each cluster's OIDC provider and the service account in subSame trust policy for every cluster; the association maps role to service account
Reuse across clustersTrust policy edited per clusterRole reused without editing
Where it runsEC2 nodes and FargateLinux EC2 nodes only (not Fargate)

EC2, ECS and Lambda

EC2 uses instance profiles (credentials delivered and rotated through the instance metadata service — require IMDSv2), ECS tasks use task roles, and Lambda uses its execution role. All are role sessions, which is why a second AssumeRole from them is role chaining (see the session section).

Servers outside AWS

MechanismCredential the server holdsWhat it gets
IAM Roles AnywhereAn X.509 certificate issued by a CA you registered as a trust anchor (AWS Private CA or your own CA bundle)Temporary credentials for a role named in a profile, per workload
Systems Manager hybrid activationAn activation code/ID used once to register the server as a managed nodeCredentials for the one IAM service role chosen for the activation, used by the SSM Agent
IAM user signing certificateA long-term certificate attached to an IAM userLong-term authentication for a few legacy APIs — not a workload-identity pattern

Operating Roles Anywhere: the workload runs the AWS-supplied credential helper (aws_signing_helper) as a credential_process in its AWS config, so every SDK and the CLI pick up the credentials transparently. The role's trust policy names the rolesanywhere.amazonaws.com service principal and must allow sts:AssumeRole, sts:TagSession and sts:SetSourceIdentity; conditions on the certificate's attributes (for example its subject) scope which certificates may use the role. Roles Anywhere does not call OCSP or CRL distribution points: revoking a certificate means importing a CRL (ImportCrl). A CRL stops new sessions only — sessions already issued stay valid until they expire or are revoked at the role.

Amazon Cognito: user pools and identity pools

Amazon Cognito authenticates your application's end users, and its two halves do different jobs. A user pool is a user directory and OIDC provider: it signs users in (passwords, MFA, social or SAML sign-in) and issues JWTs — an ID token with identity claims, an access token with scopes for calling APIs, and a refresh token. A user pool by itself grants no AWS access. An identity pool exchanges a token from a user pool (or another provider) for temporary AWS credentials for an IAM role.

Identity pool roles and per-user scoping

  • Authenticated and guest roles. An identity pool has a role for authenticated identities and, if guest access is enabled, a separate role for unauthenticated (guest) identities. A guest identity is not bound to any signed-in user, so the guest role must never grant per-user data access.
  • Role selection. By default every authenticated identity gets the pool's authenticated role. User pool group roles (the cognito:preferred_role and cognito:roles claims) take effect only when the identity pool is set to choose role from token; rules-based mapping is the alternative.
  • Per-user scoping. To confine each user to their own S3 prefix or DynamoDB partition, use the policy variable ${cognito-identity.amazonaws.com:sub}, which resolves to the caller's identity ID. ${aws:username} does not exist for role sessions, so a policy built on it matches nothing.
  • Trust policy. The identity pool roles trust cognito-identity.amazonaws.com with conditions on cognito-identity.amazonaws.com:aud (the identity pool ID) and cognito-identity.amazonaws.com:amr (authenticated or unauthenticated).
  • Flows. The enhanced flow (GetId then GetCredentialsForIdentity) is the default and lets Cognito choose and assume the role server-side; the basic flow has the client call AssumeRoleWithWebIdentity for a role it names and is disabled unless you turn it on.

App clients

A browser or mobile app cannot keep a secret, so it uses a public app client with no client secret. If the app client has a secret, every user pool API call must include a SECRET_HASH computed from it, and a client-side app that omits it fails. Client-side apps therefore use a public app client, and the secret stays only in server-side (confidential) clients.

Amazon S3 presigned URLs

An S3 presigned URL is a request already signed with someone's credentials, so whoever holds the URL performs that one operation as the signer, with the signer's permissions, until it expires. Creating one needs no extra permission; using it succeeds only if the signer could perform the operation at the moment of use.

  • Expiry. A SigV4 presigned URL can be valid for at most 7 days (the S3 console caps its own at 12 hours). It also stops working when the credentials that signed it expire, so a URL signed with a one-hour role session dies after that hour regardless of the expiry requested — sign with credentials that outlive the URL's intended life.
  • Bucket-wide cap. A bucket policy can deny requests whose signature is older than a limit with the s3:signatureAge condition key, measured in milliseconds, regardless of what expiry the signer chose.
  • Encryption. For objects encrypted with SSE-KMS, the signer needs the KMS permissions too: kms:GenerateDataKey for uploads and kms:Decrypt for downloads.
  • Choosing the signer. Sign with a dedicated identity that can do only what the URLs should allow (one prefix, one operation), so a leaked URL — or a bug in the code that generates URLs — cannot reach anything else.

Troubleshooting authentication failures

Authentication failures are diagnosed from the error code and from CloudTrail, which records STS calls — including failed ones — with the caller, the target role and the error.

ErrorMeaningTypical fix
AccessDenied on an AssumeRole* callThe caller is not allowed to call it, or the trust policy did not match the caller or a conditionCheck both sides (below)
InvalidClientTokenIdThe access key ID or security token is not recognized — for example a deactivated or deleted access keyUse a valid, active credential
ExpiredTokenThe session outlived its durationRe-authenticate or let the SDK refresh; retrying the same token never works
RegionDisabledExceptionSTS is deactivated in that Region for the accountActivate the Regional STS endpoint or call another Region's endpoint
ValidationError on durationThe requested duration exceeds the role maximum or, when chaining, one hourRequest less, raise the role maximum, or remove the chain

AssumeRole AccessDenied is two-sided

Side one: the caller's identity-based policy must allow sts:AssumeRole on the role's ARN, with no SCP or permissions boundary denying it. Side two: the role's trust policy must name the caller (or its account) as a Principal, and every condition must hold — the vendor's ExternalId, MFA present (fix: get an MFA session from GetSessionToken or pass the MFA code on AssumeRole), sts:TagSession or sts:SetSourceIdentity when tags or a source identity are passed. A trust policy that names a since-deleted role shows its unique ID and will not match a recreated role of the same name.

Tokens across Regions

Session tokens from a Regional STS endpoint are valid in every Region. Session tokens from the global endpoint are, by default (version 1), valid only in Regions enabled by default, so they are rejected in opt-in Regions. Either call a Regional endpoint, or set the account's global endpoint token version to version 2 (the IAM account setting, or SetSecurityTokenServicePreferences) — version 2 tokens are longer, so check any system that stores tokens.

Clock skew

SAML assertions and OIDC tokens carry validity windows; a drifted IdP clock produces rejections that look like expiry.

Troubleshooting federation, IAM Identity Center, Directory Service, and Cognito

Federation and directory failures leave different evidence depending on how far the sign-in got, so locate the failing step before changing anything.

SAML federation to IAM

SymptomWhere the evidence isCause and fix
Sign-in page rejects the response; no AssumeRoleWithSAML event in CloudTrailThe AWS sign-in endpoint's error page (and the IdP's logs)The assertion is missing a required attribute — Role or RoleSessionName — or the Role value is malformed; fix the IdP's attribute mapping
Failed AssumeRoleWithSAML events with AccessDeniedCloudTrailThe trust policy's conditions do not match — commonly SAML:aud not listing the sign-in endpoint the IdP posts to
Failed AssumeRoleWithSAML on durationCloudTrailThe SessionDuration attribute asks for more than the role's maximum session duration
Every user and every group fails at onceCloudTrail and the IdPThe IdP's signing certificate rolled over or expired and the IAM SAML provider still holds the old one; upload the IdP's new metadata

For resiliency, an IdP can post to Regional sign-in endpoints (such as https://us-west-2.signin.aws.amazon.com/saml) as well as the global one. The trust policy's SAML:aud condition must list every endpoint the IdP uses, or sign-ins through the missing one fail. When tags are passed, a role without sts:TagSession in its trust policy fails for everyone who selects it.

IAM Identity Center

  • Permission set changes not taking effect. Editing an assigned permission set in the console reprovisions it automatically. Changing it through the API (for example PutInlinePolicyToPermissionSet or attaching a managed policy) updates only the template until you call ProvisionPermissionSet to push it to the accounts.
  • Sessions too short or too long. The permission set's session duration (1 to 12 hours, default 1 hour) governs the account credentials; the access portal session is a separate setting. Do not edit the AWSReservedSSO_ role to change it — the change belongs on the permission set.
  • Delegated administrator cannot change a permission set. A delegated administrator cannot modify permission sets provisioned in the management account; those are managed from the management account.
  • User cannot sign in with an external IdP. The user was never provisioned (SCIM not configured, the SCIM token expired, or the user is outside the synced groups), or the manually created user name does not match the IdP's.
  • No AWS account shown in the portal. The user or group has no account assignment for any permission set.

AWS Directory Service

With AD Connector, authentication stops when the connector cannot reach the on-premises domain controllers (security groups, routing, DNS) or when the service account's password changed in AD but was not updated in Directory Service. With AWS Managed Microsoft AD, users from the on-premises forest cannot authenticate to Identity Center unless the forest trust is two-way.

Amazon Cognito

  • API Gateway Cognito authorizer returns 401. With no authorization scopes on the method, the authorizer expects the ID token; with scopes configured, it expects an access token carrying one of them. Sending the other token type fails.
  • Identity pool rejects a user pool token. Identity pool authentication providers are registered as a user pool ID plus app client ID; a token from an app client not listed there is treated as an unsupported provider.
  • Credentials issued but role not assumed. Check the role's trust conditions on cognito-identity.amazonaws.com:aud (the right identity pool ID) and amr.
  • SECRET_HASH errors. The app client has a secret that a public app cannot hold; use a public client.

Tip. Stems for this task usually turn on one precise authentication behaviour. Know which condition operator catches requests signed with long-term keys and why an MFA enrollment exemption must sit inside the deny; what each STS API's credentials can do (MFA context, IAM and STS calls, session policies, durations) and that chained role sessions are held to one hour; how session tags, transitive tags and source identity behave through a chain; who generates an external ID and why account or IP conditions do not stop a confused deputy; the claim formats an OIDC trust policy checks; how Identity Center's identity sources, SCIM provisioning and MFA settings interact; and how Cognito roles, policy variables and token types work. Troubleshooting stems give you an error code or a CloudTrail record and expect you to locate the failing step — caller policy, trust policy, assertion attribute, duration, provisioning, directory trust or token type.

Key takeaways
  • Enforce MFA with an explicit deny using BoolIfExists on aws:MultiFactorAuthPresent (or Null on aws:MultiFactorAuthAge) and put the enrollment carve-out inside the deny with NotAction — a separate Allow cannot beat an explicit deny.
  • FIDO2 security keys and passkeys resist real-time phishing because they sign for the origin; any typed code, virtual or hardware TOTP, can be relayed. SMS is not an IAM MFA option, and each IAM user can register up to eight devices.
  • Choose the STS API by caller: AssumeRole for AWS principals, AssumeRoleWithSAML and AssumeRoleWithWebIdentity for federation, GetSessionToken for an MFA session from access keys. GetFederationToken sessions carry no MFA, cannot call IAM, and cannot assume roles.
  • Role chaining (including from EC2 instance profile credentials) is limited to one hour, and a chained request above 3,600 seconds fails rather than being shortened.
  • Session tags need sts:TagSession in every reachable role's trust policy, transitive tags cannot be changed later in a chain, and source identity is set once and recorded in every CloudTrail event of the chain.
  • The external ID works only because the vendor generates a unique value per customer and never lets customers choose it; account, role or IP conditions cannot stop a confused-deputy request.
  • IAM Identity Center provisions permission sets as roles across accounts; with an external IdP, users must be provisioned (SCIM, token valid one year) before SAML sign-in, and MFA is enforced at the IdP.
  • Workloads authenticate without stored keys: OIDC with a tight sub condition for CI, EKS Pod Identity or IRSA for pods, instance profiles on EC2, Roles Anywhere certificates for servers outside AWS, and Cognito identity pools for app users.
  • Diagnose by evidence: a SAML response missing its Role attribute fails before any AssumeRoleWithSAML event, while trust-condition and duration problems show as failed AssumeRoleWithSAML events in CloudTrail.

Frequently asked questions

How do you enforce MFA for all IAM users in AWS?

Attach an explicit deny that blocks every action when aws:MultiFactorAuthPresent is false, using BoolIfExists so requests signed with long-term access keys (which never carry the key) are denied too. List the actions a user needs to enroll a device — such as iam:CreateVirtualMFADevice, iam:EnableMFADevice, iam:ListMFADevices, iam:ResyncMFADevice and iam:GetUser — in the deny's NotAction, because a separate Allow cannot override an explicit deny. For workforce users at scale, federate through IAM Identity Center and enforce MFA there or at the identity provider.

Which MFA types are phishing-resistant on AWS?

FIDO2 security keys and passkeys are phishing-resistant because the authenticator checks the website's origin before it signs, so a response produced for a lookalike domain is useless on the real AWS sign-in page. Virtual authenticator apps and hardware TOTP tokens both produce a code the user types, which a real-time phishing proxy can relay. SMS is not supported for IAM MFA. Each IAM user (and the root user) can have as many as eight MFA devices registered, so keeping a backup device is good practice.

What is the difference between AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity?

All three return temporary credentials for an IAM role, but they authenticate the caller differently. AssumeRole requires the caller to already hold AWS credentials and is used for cross-account, privilege-switching and third-party access. AssumeRoleWithSAML accepts a SAML 2.0 assertion from a trusted corporate identity provider, and AssumeRoleWithWebIdentity accepts an OIDC token from a trusted provider such as GitHub Actions or an EKS cluster; neither needs existing AWS credentials.

What is the difference between GetSessionToken and GetFederationToken?

GetSessionToken gives an IAM user temporary credentials with the user's own permissions and can include an MFA code, so the session satisfies MFA conditions; it accepts no session policy and can call IAM only if MFA was supplied. GetFederationToken is for a custom identity broker: it takes a name and a session policy (without one the session has no permissions), cannot carry MFA, cannot call IAM, and can call no STS operation except GetCallerIdentity, so it cannot assume a role.

What is the maximum session duration for AWS STS temporary credentials?

A role session can last up to the role's maximum session duration, which is set between 1 and 12 hours (default 1 hour). Role chaining — assuming a role with role-session credentials, including EC2 instance profile credentials — is limited to one hour, and a chained request for more than 3,600 seconds fails. GetSessionToken and GetFederationToken run from 15 minutes to 36 hours for an IAM user and at most 1 hour for the root user.

What is an external ID and who should create it?

An external ID is a value a third party passes as the ExternalId parameter when assuming a role in your account, checked by an sts:ExternalId condition in the role's trust policy. The vendor should generate a unique value for each customer and never let customers choose it; that is what stops the confused deputy, where one customer tricks the vendor into using its trusted access against another customer's role. Conditions on the vendor's account or IP range do not help, because the vendor is the legitimate caller in that attack.

Why does AssumeRole fail with AccessDenied even though my policy allows it?

Because role assumption must be allowed on both sides. Your identity-based policy must allow sts:AssumeRole on the role's ARN with no SCP or boundary denying it, and the role's trust policy must name you or your account and have every condition met — external ID, MFA, sts:TagSession when tags are passed, sts:SetSourceIdentity when a source identity is set. A trust policy that named a since-deleted role will not match a recreated role of the same name. The AssumeRole event in CloudTrail shows the caller and the error.

Should I use IAM Identity Center or SAML federation directly to IAM?

Use IAM Identity Center for workforce access across an organization: permission sets are provisioned as roles in every assigned account, SCIM keeps users and groups in step with an external identity provider, and users get one portal with short-lived credentials. Direct SAML 2.0 federation to IAM needs an IAM SAML provider and roles in every account, so it suits a single account, legacy integrations, or brokers that must call AssumeRoleWithSAML themselves.

Source

This lesson covers the "Identity and Access Management" domain of the official SCS-C03 exam guide. Vendors revise their guides — check the source for the current version.

Test yourself on this topic
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.

Spotted a mistake in this lesson?