SSO and Federation
One login for everything sounds simple. The trust that makes it work is where it breaks.
What you will learn
- -Tell SAML, OAuth 2.0, and OIDC apart and know which one authenticates
- -Explain the signed-assertion trust that federation rests on
- -Name the attack classes that fall out of a skipped validation step
You click "Sign in with Google" on Slack and you are in, no Slack ever typed. That is doing its job: Slack trusts Google to vouch for who you are. the trust wrong and one forged an attacker into every connected app at once, which is why this is worth understanding cold rather than as a vendor diagram.
Two words people use loosely. , single sign-on, means one gets you into many apps. Federation is SSO that crosses an organizational or boundary: your company's vouching for you to a third-party it does not . All federation is SSO. Not all SSO is federated.
Three get conflated constantly, and the difference is the whole lesson. is the old enterprise workhorse, XML-based, assertions posted through the browser. is not authentication at all, it is delegated : it hands an app an to call an on your behalf. OIDC, , is a thin authentication layer built on top of OAuth 2.0 that adds an id_token, a signed that actually states who you are.
The classic mistake is using an OAuth access token as proof of . An access token says "the bearer may call this API." It says nothing about who the bearer is. Apps that read an access token and log you in as whoever it belongs to get bitten by token substitution: swap in a token minted for a different and you can end up authenticated as someone else. OIDC exists precisely because OAuth was never designed to answer "who are you."
The trust is a signature
Roles first. The IdP, identity provider, is who vouches: Okta, Entra ID, Google, Ping. The SP or RP, service provider or relying party, is the app that trusts them. The whole model rests on the SP validating a the IdP produced with its .
In SAML the IdP returns a signed assertion, and the SP has real work to do. Check the ds:Signature against the IdP's . Check that Audience names this SP and not some other one. Check that NotOnOrAfter has not passed and that InResponseTo ties back to a request it actually sent. Skip any of those and you have a hole someone will find.
$echo $SAMLRESPONSE | base64 -d > resp.xml$xmllint --format resp.xml | less$grep -c ds:Signature resp.xmlThe attack classes follow directly from that checklist. Unsigned assertions accepted, because the SP never enforced a signature at all. XML signature wrapping, XSW, where you keep the signed element technically valid but add a second unsigned assertion that the parser reads instead of the real one. Golden SAML, where an attacker who has stolen the IdP signing key forges assertions for any user, and no password reset helps because the key itself is trusted.
On the OAuth and OIDC side the failures are their own family. A loose redirect_uri allowlist that lets you send the authorization code to a you control. An id_token whose nonce, iss, and aud the relying party never bothers to check, so a token from another issuer or replayed from another session sails through.
Forging assertions and tampering with flows against a live IdP is an attack on production identity infrastructure. Build the lab instead: stand up a Keycloak or SimpleSAMLphp IdP, wire a test SP to it, and break that. Burp's SAML Raider extension replays and mutates assertions safely against a target you control, and PortSwigger has OAuth and SAML labs for exactly this.
An app logs users in by reading the OAuth access token it receives and trusting whatever user it maps to. Why is that a problem?