cd ../blog
AWSSecurityIdentityIAM Identity CenterSCIM

One Off Switch: Moving AWS Sign-In to the Company Identity Provider

October 28, 202612 min read

It started with a simple question: how does someone without AWS access get an API key into Secrets Manager without pasting it into chat? The answer exposed a bigger gap. AWS kept its own user list, separate from the company's identity provider. Here's how we moved IAM Identity Center to an external IdP, the production details that make it safe (break-glass, session lifetimes, SCIM token expiry, least privilege), and why the off switch is only as fast as you engineer it to be.

The Problem

It started as a casual conversation about secrets. One person had generated an API key for a third-party email service. They sent it to a second person over team chat, who forwarded it to a third, the one with access to AWS Secrets Manager. Three hops, two chat messages, one key now living in chat history and search indexes indefinitely.

The obvious question was "what should the person in the middle have done instead?" They had no AWS access at all. The textbook answer is easy to write down:

  • ▸Create the secret container ahead of time. We already do that in Terraform, with values set out-of-band.
  • ▸Give the person a permission set that allows secretsmanager:PutSecretValue on that one secret's ARN, and not GetSecretValue. They can write the value; they can never read it, or anything else, back.
  • ▸Take the access away when they're done.

Then the follow-up: "they don't have AWS, but they do have an account in our identity provider." Fine, I said. If AWS sign-in is federated to the company IdP, add them to a group, the group maps to that permission set, done in ten minutes.

So I checked. It wasn't.

AWS IAM Identity Center was running on its own built-in directory. Seven users, created by hand. Three groups, created by hand. Usernames that weren't email addresses. None carried an external ID, which is what you'd see on users provisioned from an outside identity provider. The company's IdP, the one everyone uses for email, chat and every internal app, had no idea AWS existed.

That turned a ten-minute secret-sharing fix into "create them a whole second account." It also surfaced a much bigger problem than one API key.

Why a Separate AWS Directory Is a Real Risk

Nobody sets out to build a second identity system. It happens because Identity Center's built-in directory is the default, works on day one, and seven users feels small enough to manage by hand. All true. Here's what it costs anyway:

  1. ▸Offboarding is two steps, and the second one gets forgotten. A leaver's IdP account is disabled by a well-practised HR process. Their AWS account isn't, because it lives somewhere that process has never heard of. The failure mode is a former employee with admin on production accounts that hold sensitive customer data.
  2. ▸Two sets of sign-in rules. The IdP has MFA policy, device compliance, risky-sign-in detection and session controls, all tuned by whoever runs identity. AWS had its own MFA settings that nobody was watching.
  3. ▸Access was hand-built per person, and mostly admin. Every "can you give X narrow access to Y" meant creating an AWS user. That friction is exactly why secrets end up in chat, and why "just give them admin" becomes the default.
  4. ▸Audits got split answers. "Who can reach production, and how is that reviewed?" needed evidence from two directories that disagreed about who works here.

The Design

IAM Identity Center can use an external identity provider as its identity source. Two protocols do the work:

  • ▸SAML 2.0 for sign-in. People authenticate at the IdP, under the IdP's MFA and conditional-access policies, and arrive in AWS already signed in.
  • ▸SCIM for provisioning. The IdP pushes users and groups into Identity Center and keeps them in sync, including disabling and removing them.

On top of that, the rules we set for ourselves:

  • ▸Groups are the only unit of access. Permission sets are assigned to IdP-owned groups, never to individual users. Joining, moving and leaving become group membership changes in the one place HR already manages.
  • ▸Access is code. Permission sets and account assignments live in Terraform, reviewed like any other change. The IdP decides who is in a group; Terraform decides what that group can do where. Neither side can quietly widen access on its own.
  • ▸Least privilege by default, elevation on purpose. Everyday groups get read-only or scoped roles. Admin is a separate group, kept small, with a shorter session. If your IdP supports just-in-time group membership (Entra's Privileged Identity Management for Groups, for example), admin becomes something you activate for a few hours with a reason, not something you hold permanently.
  • ▸Narrow, temporary access is a pattern, not a favour. The write-only secret permission set from the start of this post is now a group. Someone is added to it for an afternoon, puts the value in, and is removed.

What didn't change, which mattered for buy-in:

  • ▸The access portal URL stayed the same, and so did aws sso login and every engineer's CLI profiles.
  • ▸CI was untouched. Pipelines that authenticate with OIDC roles (GitHub Actions, GitLab) never used Identity Center users.

The Cutover

Identity Center preserves existing users, groups and assignments when you switch from its own directory to an external IdP, and lets you switch back. It's tempting to rely on that and have the IdP "adopt" the hand-made users. That only works if every username exactly matches what the IdP sends at sign-in (the SAML NameID), and if SCIM matches on the same value instead of trying to create duplicates. With hand-made short usernames and an IdP that sends email-style login names, adoption would have meant renaming every user and hoping the matching held.

We didn't adopt. We replaced:

  1. ▸Break-glass first. Emergency IAM users in the management account, hardware MFA, credentials sealed, tested end to end. An EventBridge rule alerts the team on any console sign-in by those users, because every use should be an incident.
  2. ▸Inventory and export. Every user, group, membership and permission-set assignment written out, so the old state could be rebuilt by hand if the switch went badly.
  3. ▸IdP side, prepared in advance. The AWS IAM Identity Center enterprise app, new IdP groups with new names (so they could never collide with the hand-made ones), attribute mappings checked (a user missing a first name, last name, username or display name simply isn't provisioned, and the SAML NameID must be the same attribute mapped to username), externalId mapped to the IdP's immutable object ID so a name or email change never costs someone their access, and a conditional-access policy requiring MFA for the app. That last one has to exist before cutover: once the source switches, Identity Center stops doing MFA and trusts the IdP's assertion.
  4. ▸Terraform ready to apply. Assignments of the permission sets to the new groups, waiting only for the groups to exist in Identity Center.
  5. ▸Cutover, in an announced window. Switch the identity source, enable SCIM, provision a test user on demand, apply the assignments, have each person sign in and confirm they land on the right accounts with the right roles.
  6. ▸Remove the old world. The hand-made users and groups were deleted once everyone had signed in through the IdP. No AWS-native passwords or MFA devices remain to forget about.

The Production Details

This is where "it works" and "it's safe" diverge.

The off switch has a delay you have to engineer

Disabling someone in the IdP blocks new sign-ins immediately. It does not end sessions they already have. AWS documents that a disabled or deleted user with an active session keeps working until that session expires, and SCIM provisioning itself runs on a cycle, not instantly. So:

  • ▸Session lifetimes are short and deliberate. The access portal session bounds how long a leaver can keep starting new role sessions; each permission set's session duration bounds how long a role session lives. Admin gets the shortest.
  • ▸Urgent terminations have a runbook step. Disable in the IdP, then explicitly end the user's active sessions in Identity Center before deleting them. Once the user is deleted, you can no longer revoke their sessions from the console, so order matters.

SCIM tokens expire, and sign-in keeps working when they do

The SCIM access token Identity Center issues to the IdP is valid for one year. When it expires, provisioning stops: new joiners don't appear and, worse, leavers aren't disabled. Sign-in keeps working, so nobody using AWS notices. AWS does warn, through the Identity Center console and AWS Health events starting 90 days out, but a console banner nobody opens isn't an alert. We route those Health events to the team's alert channel, and separately alert on the IdP's provisioning status, since a provisioning job that keeps failing can be quarantined and stop retrying.

Nobody creates AWS users by hand anymore

Two service control policies close the side doors. One denies creating IAM users and access keys in member accounts, so "just make them an IAM user" can't quietly come back the first time someone is in a hurry. The other denies mutating Identity Store calls (identitystore:Create*, Update*, Delete*) from the account that administers Identity Center. AWS warns that hand edits to a SCIM-managed directory can drift from the IdP and won't be corrected by later syncs, which is also how someone would add themselves to an admin group without the IdP knowing.

One catch: SCPs don't apply to the management account. That's a strong reason to register a separate member account as the delegated administrator for Identity Center, keep day-to-day administration there, and treat the management account as break-glass territory with almost nobody in it.

Nested groups don't expand

Some providers, Entra among them, don't unpack nested group membership when provisioning. People go directly into the groups that map to AWS access, or they simply don't arrive.

The IdP is now a dependency

If the IdP or the federation breaks, nobody gets into AWS through Identity Center. That's the trade, and it's the right one, but only because break-glass exists, is tested, and alarms when used.

Watch both ends

The IdP's sign-in logs show who authenticated and under which policy. CloudTrail shows what they did once inside AWS. Both feed the same review, and periodic access reviews of the AWS groups (a feature many IdPs offer) turn "who can reach production" into a report rather than an investigation.

Don't switch to Active Directory by accident

Moving Identity Center's identity source to Active Directory is a different path from moving to an external IdP, and it permanently deletes every user, group and assignment. Worth knowing before anyone clicks around in that settings page.

It Isn't Specific to One Vendor

Our IdP is Microsoft Entra ID, but nothing here depends on that. Identity Center accepts any SAML 2.0 provider, and AWS documents SCIM setups for Entra ID, Okta, Google Workspace, JumpCloud, Ping, OneLogin and CyberArk. What varies:

  • ▸SCIM support. SAML-only gives you federated sign-in but leaves user creation manual, which throws away most of the offboarding benefit.
  • ▸Group sync. Not every provider syncs groups. Google Workspace, for example, provisions users over SCIM but not groups, so groups have to be managed in Identity Center directly. Check your provider's page in the AWS docs before designing around groups.
  • ▸Policy and elevation features. Conditional access, device trust and just-in-time access exist under different names and different licence tiers. For Entra, SCIM provisioning and group assignment need P1; Privileged Identity Management and access reviews need P2 or ID Governance. Know what your plan includes before promising "zero cost."
  • ▸One identity source at a time. Identity Center can't put half the team on one IdP and half on another.

The rule of thumb: use the identity provider your people already sign in with every day. The whole point is that one account, disabled once, turns off everything.

What It Provided

  • ▸A clean answer to the original question. Getting a secret into AWS without chat is now a short-lived group membership and a write-only permission set. Nothing is pasted anywhere.
  • ▸Offboarding in one place. Disabling the IdP account blocks new AWS sign-ins at once, provisioning disables the AWS user on its next cycle, short sessions bound everything else, and the runbook covers the urgent case.
  • ▸Fewer standing admins. Moving to group-based permission sets was the moment to stop handing out AdministratorAccess by default.
  • ▸One audit answer. Who can reach production is a list of group members, with sign-in logs on one side and CloudTrail on the other.
  • ▸A cheap check for any AWS organisation. In Identity Center, open Settings and look at Identity source. If it says "Identity Center directory" and your company has an IdP, you have two lists of who works here.

And the key that started it all was rotated. Deleting the chat messages alone doesn't remove every copy.

Future Implications

Small teams treat identity as a setup step: get everyone into AWS, move on. That's understandable at seven users. But the number of systems holding real access keeps growing (cloud accounts, data warehouses, CI, AI tooling with API keys of its own), and every one that keeps its own user list is another place offboarding can silently miss. The cheapest time to federate is when there are only seven accounts to move. The question worth asking of every new system isn't "can people sign in?" It's "when someone leaves, does turning off one account turn this off too, and how long until it actually does?"

$ ls ../