Federation and Single Sign-On in the Cloud
Federation is the arrangement by which a cloud provider trusts an external identity provider (IdP) to vouch for who a user is, and — on the strength of that vouching — mints a set of short-lived, scoped cloud credentials for them. Its point is to break the tie between “a human (or an external system) that needs cloud access” and “a permanent cloud secret sitting in that human’s hands.” Instead of every engineer holding a long-lived AWS access key, a Google service-account key file, or an Azure client secret, they authenticate once to the corporate IdP (Okta, Microsoft Entra ID, Ping, Active Directory Federation Services, Google Workspace), and the cloud hands back a session that expires in an hour or a workday. This note is the cloud-side of that handshake: how the trust relationship is declared, how a Security Token Service (STS) exchanges an external assertion for temporary credentials, and why humans should never hold static keys. The wire-level mechanics of the assertions themselves — how a SAML 2.0
<Assertion>is signed, how an OpenID Connect (OIDC) ID token’s claims andiss/aud/subare validated — belong to the Authentication MOC; here we pick up where the IdP has already authenticated the user and asks the cloud, “now give this person credentials.”
Boundary with the Authentication MOC
This note owns the cloud handoff: the trust object you create in IAM, the STS credential-exchange call, and the temporary-credential lifecycle. It deliberately does not re-teach SAML 2.0 or OIDC as protocols — the redirect/POST bindings, assertion signing, ID-token vs access-token distinction, PKCE, and discovery documents live in Authentication MOC. When this note says “the IdP returns a signed SAML assertion” or “the IdP issues an OIDC ID token,” follow the protocol depth there.
Mental Model — the cloud does not authenticate you, it trusts someone who did
The single idea to hold onto: in a federated setup, the cloud provider is not the authenticator. It never sees the user’s password, never runs the multi-factor prompt, never owns the account lifecycle. All of that is delegated to an external IdP the organization already runs. The cloud’s job shrinks to two things: (1) hold a trust anchor — the IdP’s signing metadata or OIDC issuer URL, registered ahead of time — and (2) run a token exchange — accept a freshly-signed assertion, verify it against that anchor, and vend back temporary credentials whose permissions are governed by a role the customer defined.
flowchart LR subgraph ORG["Your organization"] U["Human user<br/>(or external workload)"] IDP["Identity Provider<br/>Okta · Entra ID · Ping<br/>ADFS · Google Workspace"] end subgraph CLOUD["Cloud provider"] TRUST["Trust anchor<br/>SAML metadata / OIDC issuer<br/>registered in IAM"] STS["Security Token Service<br/>(STS-style exchange)"] ROLE["Role / permission set<br/>defines what the session can do"] CREDS["Temporary credentials<br/>expire in minutes–hours"] end U -->|"1. authenticate<br/>(password + MFA)"| IDP IDP -->|"2. signed assertion / ID token"| U U -->|"3. present assertion"| STS TRUST -.->|"validates signature"| STS ROLE -.->|"scopes permissions"| STS STS -->|"4. mint"| CREDS CREDS -->|"5. call cloud APIs"| ROLE
What it shows and the insight to take: the credential the user finally wields (box 4) is derived, not stored. The only durable secret in the whole picture lives inside the IdP (the user’s password) and inside the cloud’s trust anchor (the IdP’s public signing key — not a secret at all). Nowhere does a long-lived cloud access key get created, copied to a laptop, or checked into a repo. Kill the user in the IdP and every future exchange fails; the blast radius of a compromised session is bounded to its short lifetime.
Why humans must never hold long-lived access keys
Every provider now says this in almost the same words, and the reasoning is worth stating mechanically rather than as a slogan. A long-lived credential — an AWS IAM user access key, a downloaded GCP service-account JSON key, an Entra app client secret — has four fatal properties:
- It does not expire on its own. An AWS access key is valid until someone explicitly deactivates it. A leaked key from a git commit three years ago still works today unless it was manually revoked.
- It is bearer-only and copyable. Possession is authorization. There is no second factor at the moment of use, no binding to a device, no “was this really the user?” check. Anyone who reads the string is the user.
- It is invisible in the org’s identity system. A standalone access key is not tied to the joiner-mover-leaver lifecycle. When an employee leaves and their Okta account is disabled, a static AWS key they created still functions — the two systems don’t know about each other.
- Rotation is manual and therefore rare. Because rotating means updating every place the key is embedded, teams avoid it, and keys live for years.
Federation removes all four. The credential the user gets is (1) time-boxed — AWS AssumeRoleWithSAML credentials default to one hour and cap at the role’s maximum session duration of 1 to 12 hours (AWS STS AssumeRoleWithSAML); (2) issued only after a fresh IdP authentication that can demand MFA; (3) governed by the IdP’s lifecycle, since no assertion is minted for a disabled account; and (4) rotated automatically because it is re-minted on each login. AWS’s own guidance frames IAM Identity Center as providing “one point of federation” so that “you only federate once” rather than provisioning per-user keys (AWS IAM Identity Center). Microsoft states flatly that manually-handled secrets “are a known source of security issues and outages” and that managed/federated identities “eliminate the need for developers to manage these credentials” (Entra managed identities).
Uncertain
Verify: the exact default and maximum session-duration numbers for GCP and Azure human federation (I pinned AWS at 1 h default / 1–12 h max from the STS API reference, and the GCP/Azure machine-token lifetime at ~1 h from their metadata docs, but the provider docs fetched here did not state an explicit maximum session length for a human Workforce Identity Federation / Entra SSO session). Reason: the workforce/SSO pages fetched described the exchange as returning a “short-lived” token without a stated ceiling. To resolve: consult GCP’s Security Token Service quota page and Entra ID’s Conditional Access / token-lifetime configuration docs.
#uncertain
The SAML 2.0 federated exchange (workforce SSO)
Security Assertion Markup Language (SAML) 2.0 is the older, enterprise-heavy federation standard, and it remains the default for workforce single sign-on — humans logging into the cloud console. The flow below is AWS’s AssumeRoleWithSAML, but Google’s Workforce Identity Federation and Azure’s Entra-fronted app federation follow the same shape: authenticate at the IdP, receive a signed assertion, hand it to the cloud’s token endpoint, receive temporary credentials.
sequenceDiagram participant U as User's browser participant IdP as Corporate IdP<br/>(Okta / ADFS / Entra) participant STS as AWS STS participant AWS as AWS service (S3, EC2…) U->>IdP: 1. Sign in (password + MFA) Note over IdP: IdP looks up which AWS<br/>roles this user may assume IdP-->>U: 2. Signed SAML assertion<br/>(base64), lists Role ARN +<br/>SAML-provider ARN U->>STS: 3. AssumeRoleWithSAML<br/>(SAMLAssertion, RoleArn,<br/>PrincipalArn) — NO AWS creds needed Note over STS: Validates signature against the<br/>SAML provider metadata registered<br/>in IAM; checks role trust policy STS-->>U: 4. Credentials {AccessKeyId,<br/>SecretAccessKey, SessionToken,<br/>Expiration} — default 1 h U->>AWS: 5. Signed API calls with<br/>temporary credentials AWS-->>U: 6. Response (bounded by role's permissions)
What it shows and the insight to take: step 3 is the crux — AssumeRoleWithSAML “does not require the use of AWS security credentials”; the caller’s identity “is validated by using keys in the metadata document that is uploaded for the SAML provider entity” (AWS STS). The user proves nothing to AWS directly. They present a document AWS can verify was signed by a party AWS was pre-configured to trust. The two required inputs — RoleArn (which role to become) and PrincipalArn (which registered SAML provider vouched for you) — plus the base64 SAMLAssertion, are all the API needs.
Two IAM objects make this work, and they are the cloud-side setup this note owns:
- A SAML identity-provider entity in IAM. You upload the IdP’s SAML metadata document (its entity ID and public signing certificate). This is the trust anchor; without it, STS has no key to verify the assertion’s signature against.
- An IAM role with a trust policy naming that provider as a trusted principal (e.g.
"Principal": {"Federated": "arn:aws:iam::123456789012:saml-provider/Okta"}) and permitting thests:AssumeRoleWithSAMLaction. The role’s permission policies then bound what any resulting session can do.
The returned session honors the SAML assertion’s own clock: credentials last for the DurationSeconds you request “or until the time specified in the SAML authentication response’s SessionNotOnOrAfter value, whichever is shorter” (AWS STS). The assertion can also carry attributes as session tags (up to 50), enabling attribute-based access control, and a SourceIdentity that persists across role chaining for audit.
AWS IAM Identity Center (renamed from AWS Single Sign-On on 26 July 2022) is the managed layer most organizations now use instead of wiring AssumeRoleWithSAML by hand. It connects one external IdP once (SAML for authentication, SCIM for user/group sync), defines reusable permission sets (a permission set becomes an IAM role in each target account), and gives users a web access portal to pick an account+role and receive temporary credentials — the same STS temporary-credential model, packaged. Its roles are reserved (AWSReservedSSO_…) and, notably, cannot be assumed via raw AssumeRoleWithSAML (AWS IAM Identity Center).
GCP Workforce Identity Federation is the direct analogue: it lets “external workforce users — employees, partners, contractors — access Google Cloud” via SSO “without requiring Google Accounts,” using a “sync-less” model that stores no user accounts in Google Cloud (GCP Workforce Identity Federation). You create a workforce identity pool and a provider inside it describing the external IdP (OIDC or SAML 2.0 — Entra ID, Okta, ADFS, Ping). Users present IdP credentials to Google’s Security Token Service, which “verifies the identity and returns a short-lived Google Cloud access token in exchange,” following the OAuth 2.0 Token Exchange spec (RFC 8693). IdP claims map to Google attributes (google.subject is mandatory; google.groups, google.display_name optional).
Azure Entra ID occupies a slightly different position because for most Azure shops Entra ID is the IdP as well as the cloud directory — so “federation into Azure” often means federating a third-party IdP (or another Entra tenant) into Entra ID, after which Entra issues the tokens Azure Resource Manager and Microsoft Graph accept. The credential-free machine story (managed identities, workload identity federation) is covered in Workload and Instance Identity; the human-SSO story is standard Entra ID application SSO, which lives with the Authentication MOC protocol depth.
The OIDC / web-identity exchange (workloads and modern apps)
OpenID Connect (OIDC), built on OAuth 2.0, is the JSON/JWT-based successor and the standard for machine and CI/CD federation — GitHub Actions, GitLab, Kubernetes, mobile/web apps. On AWS the entry point is AssumeRoleWithWebIdentity, which “returns a set of temporary security credentials for users who have been authenticated … with a web identity provider” — “any OpenID Connect-compatible identity provider” (AWS STS AssumeRoleWithWebIdentity).
sequenceDiagram participant W as Workload<br/>(GitHub Actions job) participant OIDC as OIDC IdP<br/>(GitHub's token service) participant STS as AWS STS participant AWS as AWS service W->>OIDC: 1. Request OIDC ID token (JWT) OIDC-->>W: 2. Signed JWT — iss, aud,<br/>sub=repo:org/app:ref:main W->>STS: 3. AssumeRoleWithWebIdentity<br/>(WebIdentityToken=JWT,<br/>RoleArn, RoleSessionName) Note over STS: Fetches IdP's JWKS via the<br/>registered OIDC provider;<br/>verifies JWT signature;<br/>matches sub/aud against<br/>role trust-policy conditions STS-->>W: 4. Temporary credentials<br/>(default 1 h) W->>AWS: 5. Signed API calls
What it shows and the insight to take: the token in step 2 is a self-contained, IdP-signed JWT — no browser redirect, no human. The role’s trust policy pins which subject may assume it (e.g. only the main branch of org/app), so a leaked workflow file in a fork cannot mint your credentials. Like its SAML sibling, the call “does not require the use of AWS security credentials”; validation is by “a token from the web identity provider” (AWS STS). Tokens must be signed with RSA (RS256/384/512) or ECDSA (ES256/384/512). The response echoes SubjectFromWebIdentityToken (the JWT sub) and Audience (the aud/client ID) for audit.
The setup mirrors SAML: register an OIDC identity provider in IAM (its issuer URL and audience), then create a role whose trust policy trusts that provider and constrains sub/aud claims. GCP’s Workload Identity Federation provides the same for GCP (“access Google Cloud resources … instead of a service account key,” via workload identity pools/providers and the STS token exchange — see Workload and Instance Identity), and Azure’s Workload Identity Federation configures a federated identity credential on an app registration or user-assigned managed identity so the workload “exchanges trusted tokens from the external IdP for access tokens from Microsoft identity platform” (Entra Workload Identity Federation). Azure requires the credential’s issuer, subject, and audience to case-sensitively match the incoming token’s claims, and stores only the first 100 signing keys from the IdP’s OIDC endpoint.
Because AssumeRoleWithWebIdentity straddles both notes — it is the human-app and the workload federation call — the deeper workload-identity treatment (instance metadata, IRSA, managed identities) is in Workload and Instance Identity. This note’s concern is the federated case: an external IdP the cloud was told to trust.
The three vendors’ federation mechanisms side by side
| Concern | AWS | GCP | Azure |
|---|---|---|---|
| Human/workforce SSO | IAM Identity Center (SAML + SCIM); or raw AssumeRoleWithSAML | Workforce Identity Federation (workforce identity pools; OIDC/SAML) | Entra ID application SSO; federate 3rd-party IdP into Entra |
| Workload/CI federation | AssumeRoleWithWebIdentity + IAM OIDC provider | Workload Identity Federation (workload identity pools/providers) | Workload Identity Federation (federated identity credential on app / user-assigned MI) |
| Trust anchor object | IAM SAML provider (metadata) or OIDC provider (issuer URL) | Workforce/workload identity pool + provider | Federated identity credential (issuer/subject/audience) |
| Token exchange service | AWS STS | Google STS (RFC 8693 token exchange) | Microsoft identity platform (/oauth2/token, client-credentials w/ federated credential) |
| Result | STS temporary credentials (AccessKeyId/SecretAccessKey/SessionToken) | Short-lived Google access token (direct access or SA impersonation) | Entra access token (bearer JWT) |
| Session lifetime | Default 1 h; role max 1–12 h | “Short-lived” (STS token, commonly ≤1 h) #uncertain | “Short-lived” access token (commonly ~1 h) #uncertain |
| Protocols | SAML 2.0, OIDC | SAML 2.0, OIDC, plus X.509, AWS/Azure identities | OIDC (federated credential flow) |
What it shows and the insight to take: the vocabulary differs but the machine is identical everywhere — a pre-registered trust anchor, a token-exchange endpoint, and a short-lived derived credential scoped by a role/permission set. Learn the pattern once; the three product names are just skins over it.
Common misunderstandings and failure modes
- “Federation logs you into the cloud.” No — it logs you into the IdP, which then vouches for you to the cloud. The cloud only verifies a signature and applies a role. If you find yourself typing a cloud-native password, you are not federated.
- Over-broad trust policies. The classic OIDC federation bug is a role trust policy that trusts the provider but forgets to pin the
sub/aud. For GitHub Actions this means any repo’s workflow can assume your role. Always constrain the subject claim (repo:org/app:ref:refs/heads/main) and the audience. AWS explicitly warns about the analogous Cognito case: a trust policy without the:audcondition “creates a risk that a user from an unintended identity pool can assume the role” (AWS STS). - PII in the subject/NameID. Both AWS APIs warn that the
NameID(SAML) orsub(OIDC) lands in CloudTrail logs; use an opaque persistent identifier, not an email, to avoid leaking PII (AWS STSAssumeRoleWithSAML). - Clock skew and expiry. SAML assertions and OIDC tokens carry
NotOnOrAfter/exp. A drifting IdP or cloud clock producesExpiredToken/InvalidIdentityTokenerrors. The fix is NTP discipline, not longer token lifetimes. - Confusing federation with directory sync. SCIM provisioning (pushing users/groups into IAM Identity Center) is not the authentication path; it just pre-creates the principals and their group memberships. Authentication still happens per-login via SAML/OIDC. GCP Workforce Identity Federation is deliberately “sync-less” to avoid this coupling.
- Assuming Identity Center roles via STS.
AssumeRoleWithSAML“will not work on AWS IAM Identity Center managed roles” (theAWSReservedSSO_ones) — a common trip-up when scripting against Identity-Center-provisioned access (AWS IAM Identity Center).
When to choose which
- SAML 2.0 — reach for it for human workforce SSO into consoles when your IdP is enterprise-grade (ADFS, Entra ID, Okta, Ping) and the ecosystem already speaks SAML. It is verbose XML but battle-tested for browser-mediated login.
- OIDC — the default for everything machine-to-machine and modern: CI/CD (GitHub/GitLab), Kubernetes workloads, mobile/SPA apps. JWTs are compact, JSON-native, and don’t need a browser. New integrations should prefer OIDC.
- Managed federation front-ends (IAM Identity Center, Workforce/Workload Identity Federation, Entra federated credentials) over hand-rolled
AssumeRole*calls — they centralize the trust config, add group-to-permission mapping, and give an audit trail, at the cost of a little less low-level control. - Per-service note boundary: if the “identity” is a piece of running code on a cloud VM/pod that needs credentials without any external IdP at all (an EC2 instance reading S3, a GKE pod calling BigQuery), that is not federation — it is Workload and Instance Identity, where the cloud platform itself vends the credential.
Production notes
Federation is now the default posture, not an advanced option. AWS’s Well-Architected security guidance and its own tooling push organizations off IAM users entirely and onto IAM Identity Center; the presence of long-lived IAM user access keys is a standard audit finding. GitHub’s OIDC integration with AWS/GCP/Azure is the canonical modern example — it eliminated the once-ubiquitous practice of pasting cloud keys into CI secrets, and its rollout (2021 onward) is why “store your AWS key in GitHub Secrets” is now considered an anti-pattern. The recurring real-world incident is the over-permissive OIDC trust policy: teams trust the GitHub OIDC provider but forget the subject condition, and a fork or a renamed repo gains production access. Pin the sub. The second recurring incident is residual static keys: an organization federates its humans but leaves a handful of service accounts on downloaded keys “just for that one script,” and those are what leak. The endgame is zero long-lived credentials — federation for humans and external systems, workload identity for code running inside the cloud.
See Also
- Authentication MOC — protocol depth: SAML 2.0 assertions/bindings, OIDC/OAuth 2.0 flows, JWT validation, ID-token vs access-token — everything this note hands off
- Workload and Instance Identity — the sibling primitive: giving code inside the cloud an identity with no external IdP and no embedded secret
- Cloud IAM Model Principals Roles and Policies — the roles and trust policies that federation targets
- IAM Policy Evaluation Logic — how the assumed role’s permissions are actually evaluated (explicit-deny-wins, boundaries, SCPs)
- Least Privilege and Permission Boundaries — scoping what a federated session can do
- Organization and Account Hierarchy — why IAM Identity Center federates once and fans out across many accounts
- Workload Identity (Kubernetes) — the Kubernetes-side workload-identity mechanism this connects to
- Cloud Architecture MOC — parent map (§5 Identity and Access Management)