How to Federate Okta to AWS Across an Organization Without Long-Lived Keys

October 04, 2028 · 16 min read

Security Specialty · SCS-C03 · part of The Exam Room

The situation

A growing enterprise runs 35 AWS accounts inside a single AWS Organization. Around 400 engineers, analysts, and platform staff need access across the estate, some to one account, some to fifteen, a handful to all thirty-five. The corporate IdP is Okta; every employee already signs in with a password and a TOTP or WebAuthn factor.

Today, each AWS account has its own pile of IAM users. Access keys rotate on a best-effort schedule. Offboarding is a ticket asking each account owner to remove a user manually. MFA is per-IAM-user, so every engineer enrols a separate device in every account they touch, and several haven’t.

The security team’s brief is the obvious response: zero long-lived AWS credentials, one-place provisioning in Okta, per-team permission patterns, MFA enforced universally without per-account enrolment, and reasonable operational overhead for a six-person identity team.

What actually matters

Before mapping services to the ask, worth naming the deeper properties of a correct answer.

The first thing to notice is that the problem is not really about AWS, it’s about identity ownership. A pile of 35 IAM user directories, each independently maintained, is a copy of the Okta directory that has drifted the moment it was created. The moment there are two sources of truth for who exists, there are regular reconciliation failures: the engineer who left three months ago whose key is still active in account 17, the new starter who can sign in to staging but not prod because someone forgot to mirror her IAM user, the MFA device that got re-enrolled in one account and not another. The fix isn’t better process around the two directories; it’s collapsing them to one. Everything else follows from that.

Blast radius is the next thing to weigh. With per-account IAM users, a leaked access key compromises one account. With per-account IAM users multiplied across 35 accounts, a leaked password reused across the IdP and AWS compromises as many accounts as the attacker can map. Centralising sign-in on Okta doesn’t just cut operational overhead, it means the attack surface for “employee credential takeover” is the Okta login page, which has WebAuthn, conditional access, and Okta’s own anti-phishing telemetry in front of it, not 35 password-last-changed-2022 IAM users.

Coverage of the directory’s lifecycle is what separates a good federated-access answer from a merely-functional one. Joiners are easy, everyone remembers to create the account. Leavers are hard, because offboarding is ticket work in a busy week; it’s where directories drift most. The test of a federation architecture isn’t how clean the sign-in flow looks; it’s what happens at 5pm on a Friday when HR deactivates the user. Does access across all 35 accounts end within seconds, or does it end when someone files the tickets on Monday? The gap between those two outcomes is where compromise from a disgruntled leaver lives.

Session shape and MFA enforcement deserve their own attention. A federation that issues 12-hour sessions with no MFA prompt for a privileged role is theoretically compliant and practically weak. We want Okta’s MFA factor to ride in the SAML assertion at sign-in, and we want sessions short enough that a stolen laptop mid-afternoon doesn’t authorise production writes for the rest of the day. That’s a policy question at the IdP plus a permission-set question at AWS.

Finally, there’s operational scale. Adding the 36th account should be work measured in minutes, not days. If configuring Okta for each new AWS account is a fresh SAML app and a fresh certificate rotation, someone will eventually skip it and that account will drift. The architecture that scales has Okta -> AWS configured once, with member accounts enrolled via AWS’s own org-integration plumbing.

What we’ll filter on

  1. No long-lived credentials. Every API call comes from a temporary session that expires.
  2. Single source of truth in Okta. Group memberships, employment status, MFA factor, all live in Okta.
  3. Group-to-(account, policy) mapping. An Okta group maps to a policy bundle that applies in a defined set of AWS accounts.
  4. MFA satisfied at the IdP. Okta enforces the factor; AWS trusts the assertion.
  5. Overhead that scales sub-linearly with account count. Adding the thirty-sixth account is bounded work, not a multi-day reconfiguration.

The federated identity landscape

Four approaches sit at different layers.

1. IAM users with long-lived access keys in each account. Where the team is now. Every key is a credential that can be exfiltrated, committed to a repo, or rotate-forgotten. MFA is per-IAM-user, so per-account enrolment. Provisioning is a 35-account ticket storm; a forgotten key in account 17 outlives the employee by months. Fails attributes 1, 2, 4, and 5 at once.

2. Traditional SAML 2.0 federation via IAM identity providers. In each AWS account, create a SAML identity provider (an IAM resource holding the Okta IdP’s metadata and signing certificate), then IAM roles whose trust policy references it. The Okta app produces a SAML assertion; the browser POSTs it to AWS sign-in, which calls AssumeRoleWithSAML; STS returns temporary credentials scoped to the chosen role. Satisfies attributes 1 and 4. Fails attribute 5 at this scale: the SAML identity-provider resource is per-account, so adding Okta to thirty-five accounts is thirty-five separate configurations, and every Okta certificate rotation is a thirty-five-account change. Fine for a single account. Untenable across thirty-five.

3. Amazon Cognito user pools. Cognito is a user directory for the applications you build, it’s how a mobile app or SaaS product signs in its end-users. It brokers social, SAML, and OIDC logins to produce application-layer tokens. It is not a workforce-access service: it doesn’t assign AWS console access, doesn’t integrate with AWS Organizations, and doesn’t map people to per-account IAM roles. Wrong layer of the stack.

4. AWS IAM Identity Center, with Okta as the external identity provider. Formerly AWS SSO, renamed 26 July 2022. Integrates with AWS Organizations from the management account; supports external IdPs via SAML 2.0 for authentication and SCIM 2.0 for user/group provisioning; manages permission sets as account-independent policy templates and account assignments as the (group, account, permission set) triples that materialise them. Okta is the source of truth; Identity Center is the fan-out layer.

Side by side

Option No long-lived creds Okta source of truth Group → (account, policy) MFA at IdP Sub-linear ops
IAM users + access keys per account
Per-account SAML 2.0 federation , ,
Amazon Cognito user pools ,
IAM Identity Center + Okta

For thirty-five accounts and four hundred users, Identity Center is the survivor.

Mapping Okta groups to AWS access

Okta (source of truth) corporate IdP users + MFA factors password + WebAuthn / TOTP HR lifecycle -> create / deactivate groups bi-analysts platform-admin sre-oncall finance-data read-only-exec Okta AWS IAM IC app SAML 2.0 for sign-in SCIM 2.0 for provisioning + Push Groups IAM Identity Center management account; org instance identity source: external IdP users + groups mirrored from Okta near-real-time via SCIM SAML assertion validated at sign-in permission sets (templates) BIReadOnly PlatformAdmin SREOncall FinanceDataReadWrite 1h default, 12h max session account assignments (group, account, permission set) triples, what to review quarterly assign to groups, never users AWS access portal acme.awsapps.com/start 8h default, 90d max portal session tiles: accounts x permission sets 35 member accounts roles materialise per assignment Account 111... (data platform) AWSReservedSSO_BIReadOnly_... AWSReservedSSO_PlatformAdmin_... trust: Identity Center only Account 222... (reporting) AWSReservedSSO_BIReadOnly_... AWSReservedSSO_FinanceData_... policies from permission set Account 333... (production) AWSReservedSSO_SREOncall_... AWSReservedSSO_ExecReadOnly_... hand edits get overwritten ... 32 more accounts each materialised on assignment auto-enrol on Org join no per-account SAML IdP resource no per-account cert rotation the linear-ops property SCIM sync SAML at sign-in materialise roles
Okta provisions users and groups into Identity Center via SCIM, authenticates sign-ins via SAML, and Identity Center materialises permission sets as AWSReservedSSO roles in member accounts.

Identity Center, in depth

Identity Center is three things wired together: an identity source, a set of permission sets, and a table of account assignments.

Enabling it. Identity Center is enabled from the Organization’s management account. There are two instance types, an organization instance (one per organization, supports multi-account access management) and an account instance (single-account, for isolated application deployments). The 35-account case needs the organization instance. Identity Center provisions a service-linked role in each member account so it can create and maintain roles on your behalf.

Identity sources. Three options: Identity Center directory (built-in, for tiny orgs), Active Directory (AWS Managed Microsoft AD or self-managed via AD Connector), or External identity provider (SAML 2.0 for sign-in, SCIM 2.0 for provisioning), the Okta path.

Connecting Okta. SAML and SCIM are configured independently. On the SAML side, add the Okta “AWS IAM Identity Center” app from its catalogue; the metadata and ACS URL exchange establishes the trust. On the SCIM side, Identity Center generates a SCIM endpoint URL and a bearer access token, shown once, not retrievable later. Okta then pushes user creation, attribute updates, deactivation, and group membership via Okta’s Push Groups feature. Pushed groups are what permission sets get assigned to, not individual users.

Permission sets. A permission set is a template for an IAM role. It can contain up to 10 AWS managed policies, customer managed policies referenced by name (expected to exist in each assigned account), an inline policy up to the size limit, a permissions boundary, a session duration (1 hour default, 12 hours max), and a relay state URL, the page a user lands on after picking the permission set.

Account assignments. A triple, (principal, AWS account, permission set), where the principal is an Identity Center group or (less commonly) a user. On creation, Identity Center creates an IAM role in the target account named AWSReservedSSO_<PermissionSetName>_<random-id> and attaches the permission set’s policies. The trust policy only allows assumption via Identity Center’s own flow, not via generic AssumeRoleWithSAML calls. The AWSReservedSSO_* prefix is a signal: those roles are Identity-Center-managed, and hand edits get overwritten on the next sync.

Two session clocks. AWS access portal session (default 8 hours, max 90 days) governs how often the user bounces back to Okta for a fresh SAML assertion. AWS account session (default 1 hour, max 12 hours, per permission set) governs how often the CLI refreshes credentials.

The AWS access portal URL. Default form https://d-xxxxxxxxxx.awsapps.com/start. Customisable once to a friendlier subdomain like https://acme.awsapps.com/start, one-time rename, not reversible without support.

A worked sign-in trace

Monday morning, a new BI analyst has been added to the bi-analysts Okta group by HR’s onboarding flow. The group has an Identity Center assignment giving it the BIReadOnly permission set in accounts 111111111111 (data platform) and 222222222222 (reporting sandbox). The new analyst has never signed in to AWS before.

Okta’s SCIM agent pushes her membership to Identity Center; within seconds, the assignment is live. She visits https://acme.awsapps.com/start; Identity Center redirects to Okta; Okta prompts for her password and a WebAuthn tap; the signed SAML assertion POSTs back to Identity Center’s ACS URL; Identity Center validates, matches her by NameID, and renders the portal. Two account tiles, a BIReadOnly button under each. She clicks BIReadOnly under the data platform account; Identity Center assumes the AWSReservedSSO_BIReadOnly_<id> role and STS returns temporary credentials. Later she runs aws sso login --profile bi-platform; the CLI caches temporary credentials locally and aws s3 ls just works.

Six months on, the analyst leaves the company. HR deactivates the user in Okta; SCIM pushes the deactivation; Identity Center marks the user inactive; portal and account sessions are revoked. Access ends across both AWS accounts on a single Okta change. No IAM user to delete in thirty-five places.

When traditional SAML federation is still correct

Identity Center is the correct answer for multi-account workforce access, but three cases push the other way. Legacy accounts outside the Organization (acquisitions, inherited projects) aren’t eligible for Organizations-managed assignments; per-account SAML federation with an IAM identity provider is the pattern there. Single-account sandboxes make Identity Center assignments more ceremony than the value justifies. Service-to-service and CI/CD needs a different pattern entirely. Identity Center is for humans; OIDC for GitHub Actions, IAM Roles Anywhere for off-cloud workloads, and instance/task roles for EC2 and ECS cover the machine principals.

The Cognito misconception

Cognito shows up in this space often enough to be worth naming. Cognito is for the users of your application, a mobile app you ship, a SaaS product you sell, a customer portal you run. User pools are the directory; identity pools exchange pool tokens for temporary AWS credentials via AssumeRoleWithWebIdentity, which is how a mobile app uploads directly to S3 on behalf of its end-user. None of that is workforce access to the AWS console. Engineers and analysts don’t use your application; they build it.

A Cognito user pool for engineers would require a custom admin UI for access, custom code to mint AWS credentials, no out-of-the-box MFA enforcement, no Organizations integration, and no permission-set abstraction. You would be building Identity Center, badly, from scratch.

What’s worth remembering

  1. IAM Identity Center is the workforce-access service for multi-account AWS, successor to AWS SSO, integrates with AWS Organizations from the management account, manages permission sets and account assignments.
  2. External IdP integration is SAML 2.0 for sign-in plus SCIM 2.0 for provisioning; the SCIM bearer token is shown once.
  3. Permission sets are account-independent templates of policies, permissions boundary, session duration, and relay state; they materialise as AWSReservedSSO_* IAM roles in each assigned account.
  4. Account assignments are (group, account, permission set) triples; assigning to groups rather than users is what scales.
  5. Two session clocks: portal session (default 8h, max 90d) and account session (default 1h, max 12h).
  6. Traditional SAML federation uses per-account IAM identity providers and AssumeRoleWithSAML, fine for one account, 35 separate configurations for 35 accounts.
  7. AssumeRoleWithSAML cannot assume Identity Center roles; the AWSReservedSSO_* trust policy only accepts Identity Center’s own flow.
  8. Cognito is not workforce access, it’s the identity layer for the users of applications you build; using it for engineers’ console access is a category error.
  9. MFA happens at Okta; Identity Center trusts the SAML assertion’s authentication context, so there’s no per-account enrolment.
  10. Offboarding is a single Okta change: deactivate the user, SCIM carries it, portal and account sessions revoke, access ends across every enrolled account.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.