Federation · 4 min read
SP-Initiated SSO on .NET: From WIF to Modern Libraries
Short answer
In SP-initiated SSO the application sends the user to the identity provider with an authentication request and validates the response that comes back; Windows Identity Foundation supported this for WS-Federation, not SAML 2.0 protocol, so modern .NET apps use the built-in OpenID Connect or WS-Federation handlers, or a SAML 2.0 library for ASP.NET Core.
Key takeaways
- SP-initiated flows let the SP bind the response to its own request (InResponseTo, RelayState), which IdP-initiated flows cannot.
- WIF ships in .NET Framework (System.IdentityModel) and is not part of modern .NET; it never implemented the SAML 2.0 protocol.
- For new .NET work, prefer OpenID Connect; use a maintained SAML 2.0 library when a partner requires SAML.
Windows Identity Foundation was Microsoft's claims-based identity library for .NET Framework. It made federated sign-in look easy: add some configuration, and your ASP.NET app trusted AD FS. It also caused a lot of confusion, because many people assumed it did SAML 2.0 SSO. It did not, quite. Here is how SP-initiated SSO works and what to use on .NET today.
What is SP-initiated SSO?
The user starts at the application (the service provider), which redirects them to the identity provider with a request, and then validates the IdP's response against that request.
In SAML 2.0 terms:
- The user opens
https://app.example.com/reports. - The SP creates an
AuthnRequestwith a uniqueID, and sends it to the IdP's SSO URL, usually with the HTTP-Redirect binding (DEFLATE, base64, URL-encode) and aRelayStatethat remembers where the user was going. - The IdP authenticates the user and posts a
Responseback to the SP's Assertion Consumer Service URL with the HTTP-POST binding.InResponseTocarries the request's ID. - The SP validates the signature, issuer, audience, recipient, time conditions and
InResponseTo, then creates a session and sends the user to theRelayStatelocation.
Paste either message into the SAML Decoder: it inflates Redirect-binding requests and shows the InResponseTo, Destination and condition values of a response.
Why is SP-initiated safer than IdP-initiated?
Because the SP can tie the response to a request it made, which stops unsolicited responses and some login CSRF.
With IdP-initiated SSO the SP receives a response it never asked for, so it cannot check InResponseTo. Attackers can try to replay or inject assertions, or log a victim in to the attacker's account. Many security guides recommend disabling IdP-initiated flows unless an application truly needs them, and adding replay detection on assertion IDs when you keep them.
What did WIF actually support?
WS-Federation passive sign-in and WS-Trust, with SAML 1.1 and 2.0 tokens, but not the SAML 2.0 protocol and its bindings.
This is the source of the confusion. WIF could consume a SAML 2.0 assertion, the token, when it arrived inside a WS-Federation response. It did not generate SAML 2.0 AuthnRequest messages or handle the SAML Web Browser SSO profile. Microsoft published a SAML 2.0 extension as a preview, but it never became a supported release. From .NET Framework 4.5, WIF was folded into the framework itself (System.IdentityModel and System.IdentityModel.Services).
So "SP-initiated with WIF" meant WS-Federation: the app redirected to AD FS with wa=wsignin1.0, wtrealm and wctx, and AD FS posted back a wresult containing a token.
What should I use on .NET today?
OpenID Connect where possible; the WS-Federation handler for existing AD FS apps; a SAML 2.0 library when a partner requires SAML.
| Need | Option |
|---|---|
| New app, any modern IdP | ASP.NET Core OpenID Connect handler, or Microsoft.Identity.Web for Entra ID |
| Existing WS-Federation app on AD FS | ASP.NET Core WS-Federation handler |
| Partner requires SAML 2.0 | A maintained open-source or commercial SAML 2.0 library for ASP.NET Core |
| Legacy .NET Framework app | Keep WIF running, plan migration; OWIN middleware offers OIDC and WS-Fed |
| Token validation only | Microsoft.IdentityModel libraries (JWT and SAML token handlers) |
Whichever library you pick, check that it validates InResponseTo, rejects unsigned assertions, enforces audience and recipient, and has a recent release history.
What are the common SP-initiated mistakes?
Ignoring RelayState validation, skipping InResponseTo, and trusting the wrong signature.
- An unchecked
RelayStatecan become an open redirect. Only allow relative paths or a known list. - Store the request ID with the user's pre-login session and require
InResponseToto match. - Verify the signature covers the assertion you actually read; XML signature wrapping attacks hide a second, unsigned assertion.
For federation trust in general, see the federation guide; for AD FS claims, the LDAP attribute store article.
Questions
What is the difference between SP-initiated and IdP-initiated SSO?
In SP-initiated SSO, the user starts at the application, which sends an authentication request to the IdP. In IdP-initiated SSO, the user starts at the IdP portal, which sends an unsolicited response to the application. SP-initiated is safer because the response can be matched to a request.
Does ASP.NET Core support SAML 2.0 out of the box?
No. ASP.NET Core includes OpenID Connect and WS-Federation authentication handlers. For SAML 2.0 you need a third-party library, either open source or commercial.
Sources
Tagged: WIF, .NET, Microsoft, SAML, Single sign-on, AD FS, STS (security token service)