PingFederate + SAML in .NET Framework and .NET Core
How I worked through a stubborn SSO setup in an older .NET codebase and got the flow to behave.
What Usually Goes Wrong
Metadata and endpoint mismatch between SP and IdP.
Certificate rollover not handled in validation logic.
Audience/Recipient mismatch in assertion checks.
Clock skew causing intermittent token rejection.
Different middleware behavior in .NET Framework vs .NET Core.
How The Flow Works
In this flow, your app is the Service Provider (SP) and PingFederate is the Identity Provider (IdP). The app sends the user to PingFederate for sign-in, receives a SAML response at Assertion Consumer Service (ACS), validates the response, and then creates a local auth session.
What I Actually Faced
I started in an older .NET Framework codebase, and the first problem was not SAML itself. It was the framework version and the lack of a clean path to wire SSO without turning the code into a mess. OAuth examples were easy to find; SAML on my stack was not.
I upgraded the application from .NET Framework 4.0 to 4.8.1 to support a modern SAML approach cleanly.
I used Sustainsys.Saml2 because it matched the application style and reduced custom plumbing.
The real work was making the ACS, entity ID, and proxy headers line up in the deployed environment.
After that change, the integration became something I could actually maintain and troubleshoot without guessing.
Code I Added to Make It Maintainable
The key was to keep the SAML plumbing away from controllers and keep the claims mapping predictable.
public sealed class SamlOptions
{
public string EntityId { get; set; } = "";
public string AcsUrl { get; set; } = "";
public string IdpMetadataUrl { get; set; } = "";
}
public static class ClaimMap
{
public static ClaimsIdentity Map(ClaimsIdentity identity)
{
var email = identity.FindFirst(ClaimTypes.Email)?.Value ?? "";
var name = identity.FindFirst(ClaimTypes.Name)?.Value ?? "";
identity.AddClaim(new Claim("app_email", email));
identity.AddClaim(new Claim("app_name", name));
return identity;
}
}
[HttpPost]
[AllowAnonymous]
public IActionResult Acs()
{
// Validate the SAML response with the middleware, then create the local auth cookie.
// The app should only continue after the claim set has been normalized.
return RedirectToAction("Index", "Home");
}
Simple Analogy
Think of the app as a gated office building. PingFederate is the receptionist at the front desk. The user shows ID, the receptionist checks it, and then hands back a stamped visitor badge. The app only lets the user in after it sees that badge and matches it to the right person.
Data Panel
Reference table for quick scanning and comparison.
ReferenceLiveStatus
SAML Part
Plain-English Meaning
PingFederate
The front-desk identity checker.
SP / App
The building that wants to trust the check.
ACS URL
The door where the stamped pass is returned.
SAML Response
The stamped visitor badge with proof of identity.
Local auth cookie
The wristband the app gives after the visitor is accepted.
How The Flow Feels To A User
The user clicks the app and gets redirected to PingFederate.
PingFederate checks the login and creates a trusted identity assertion.
The browser posts that assertion back to your ACS endpoint.
Your app verifies the proof and creates its own session cookie.
The user lands back in the app already signed in.
Diagram 1: Standard SAML Web SSO Flow
Checklist Before Coding
Data Panel
Reference table for quick scanning and comparison.
ReferenceLiveStatus
Item
Must Match
Entity ID
SP entity ID in app and PingFederate connection config
ACS URL
Exact scheme/host/path, including trailing slash behavior
Binding
POST/Redirect expectations on both sides
Signing Certificate
Current + next cert if rollover configured
NameID / Claims
Mapped attributes needed by application authorization
MVC Mapping: SAML Config to App Flow
Teams often understand SAML settings better when they map each item to a concrete app touchpoint. Use this as a debugging bridge between PingFederate config and MVC behavior.
Data Panel
Reference table for quick scanning and comparison.
Where it fits: legacy enterprise portals, MVC 5, WebForms wrappers, or apps not yet migrated to .NET Core.
Configure cookie middleware first, then SAML middleware.
Set SP Entity ID, ACS endpoint, and IdP metadata carefully.
Enable cert validation with rollover plan (current + next cert).
Persist session securely, especially across load-balanced nodes.
Typical failure pattern: redirect loop due to cookie path/domain mismatch or callback URL mismatch.
Approach B: .NET Core (ASP.NET Core Auth Schemes)
Where it fits: modern APIs + web apps behind reverse proxy and cloud load balancers.
Set default auth scheme and challenge scheme explicitly.
Configure forwarded headers so external host/scheme are preserved.
Use robust SameSite/cookie settings for SSO redirects.
Validate ACS callback against external URL, not internal pod/host URL.
Typical failure pattern: works locally, fails in prod because proxy headers are not trusted.
Real Scenario: SSO Works in Dev but Fails After Deployment
Users click the app, get redirected to PingFederate, and authenticate successfully. The browser comes back to the app, but the deployed environment keeps looping back to login or returns an ACS error.
Data Panel
Reference table for quick scanning and comparison.
Preserve return URL safely and validate relay-state handling
Logout still appears logged in
User logs out of app, but next navigation auto-logs in
IdP session still active or local cookie not fully cleared
Implement full signout for both local cookie and SAML/IdP session
Works in local, fails in prod
Auth fails only behind load balancer
Incorrect external scheme/host due to missing forwarded headers
Enable forwarded headers and verify externally visible callback URLs
Intermittent auth failures
Random token validity errors
Clock skew / NTP drift across app nodes
Sync server clocks and tune allowed skew conservatively
Identity vs UserIdentity, Token Size, and Cookie Chunking
In many real projects, teams unintentionally duplicate claims across different identity objects (for example, base identity + user identity) or include multiple token payloads carrying similar data. This inflates auth cookie size and introduces random sign-in failures.
What Happens in Practice
Too many claims are copied from SAML assertion into local auth ticket.
App stores role/group claims at full source volume instead of app-scoped subsets.
Additional custom claims are appended in post-auth events, duplicating values.
Symptoms
Intermittent login loops after successful IdP authentication.
400 Bad Request due to header/cookie size limits.
User works in one browser/network but fails behind some proxies or WAF policies.
Where Token Chunking Helps
Cookie chunking splits large auth cookies into multiple smaller cookies so they can be transported within browser/server limits. It helps transport, but it does not solve root cause claim bloat.
Use chunking to improve compatibility with large auth tickets.
Still reduce claims to minimum required set for authorization.
Prefer reference/session storage model when claim volume is high.
Recommended Pattern
Map only essential claims from SAML response.
Normalize roles/groups into compact app-specific permissions.
Avoid duplicating same values in multiple identities/claim types.
Enable chunking if needed, then monitor cookie count/size in browser dev tools.
// Conceptual goal
// 1) keep essential claims only
// 2) enable cookie manager/chunking in auth middleware when required
// 3) validate total response header size across proxy + app stack
Same User Claim, Different Names (Claim Alias Conflicts)
Another common issue is receiving the same user attribute under different claim names. For example, one environment sends email, another sends mail, and a third sends http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress. The value is the same, but app logic can break if it expects only one key.
Typical Conflicting Aliases
User ID: sub, nameidentifier, uid, custom employee id claim.
Email: email, mail, emailaddress.
Display Name: name, given_name + family_name, custom full name claim.