SSO and SAML Implementation Guide: Enterprise Single Sign-On
Single Sign-On (SSO) is the architecture that lets enterprise users authenticate once to an Identity Provider (IdP) and then access many applications without re-entering credentials. Done correctly, SSO centralizes authentication enforcement -- MFA policies, session timeouts, and account revocation all happen at the IdP, and every connected application benefits. Done incorrectly, SSO creates a single point of compromise: one stolen IdP session or one XML signature validation bug gives an attacker access to every integrated application. This guide covers SAML 2.0 and OIDC SSO implementation, security requirements, and the vulnerabilities that are most commonly exploited in practice.
SAML 2.0 Architecture and Terminology
SAML 2.0 is an XML-based authentication and authorization protocol. Understanding its components is required to configure it correctly and securely.
Core components:
- Identity Provider (IdP): Authenticates the user and issues SAML assertions. Examples: Okta, Microsoft Entra ID (Azure AD), Google Workspace, OneLogin, PingFederate, Keycloak
- Service Provider (SP): The application relying on the IdP for authentication. Examples: Salesforce, Workday, GitHub Enterprise, your internal apps
- SAML Assertion: An XML document issued by the IdP, signed with the IdP's private key, containing the user's identity and attributes
- Metadata: XML documents exchanged between IdP and SP describing endpoints, certificates, and capabilities
SAML 2.0 assertion structure:
<saml:Assertion>
<saml:Issuer>https://idp.yourdomain.com</saml:Issuer>
<ds:Signature><!-- IdP digital signature over assertion --></ds:Signature>
<saml:Subject>
<saml:NameID Format="emailAddress">user@yourdomain.com</saml:NameID>
<saml:SubjectConfirmation Method="bearer">
<saml:SubjectConfirmationData
Recipient="https://app.example.com/saml/acs"
NotOnOrAfter="2026-05-20T10:15:00Z"
InResponseTo="_requestID123"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions
NotBefore="2026-05-20T10:05:00Z"
NotOnOrAfter="2026-05-20T10:15:00Z">
<saml:AudienceRestriction>
<saml:Audience>https://app.example.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AttributeStatement>
<saml:Attribute Name="email">
<saml:AttributeValue>user@yourdomain.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="groups">
<saml:AttributeValue>engineering</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
SP-initiated vs. IdP-initiated flow:
| Flow | Trigger | Security | Use Case |
|---|---|---|---|
| SP-initiated | User accesses SP URL, gets redirected to IdP | Higher -- includes AuthnRequest with RelayState | Standard enterprise SSO |
| IdP-initiated | User clicks app in IdP dashboard | Lower -- no AuthnRequest to validate InResponseTo | Application portals; CSRF risk |
Prefer SP-initiated flow for all applications where possible. IdP-initiated flows cannot validate the InResponseTo attribute, which is a CSRF mitigation.
SAML Security Requirements: Signature Validation and XML Attacks
SAML's most serious vulnerabilities stem from incorrect XML signature validation. These bugs have affected Okta, Duo, GitHub, and many other major platforms historically.
Critical signature validation requirements:
The SP must validate ALL of the following before trusting a SAML assertion:
- Signature exists -- reject assertions without a signature
- Signature is over the correct element -- the signature must cover the
<Assertion>element (or the entire<Response>); a signature over only part of the XML does not protect the assertion content - Signature uses a trusted key -- the signing certificate must be the IdP's registered certificate; reject if the SP resolves the key from a URL in the assertion (XML Signature Remote Code Execution pattern)
- Issuer matches -- the
<Issuer>value must match the registered IdP entity ID exactly - Audience matches -- the
<Audience>must match the SP's entity ID exactly; this prevents an assertion issued for one SP from being replayed against another - NotOnOrAfter is valid -- the assertion has not expired; reject assertions older than a few minutes
- InResponseTo matches -- for SP-initiated flows, the
InResponseTomust match a RequestID the SP actually sent - Recipient matches -- the
<Recipient>in SubjectConfirmationData must be the SP's ACS URL
XML Signature Wrapping (XSW) attacks:
XSW is a class of attacks where an attacker modifies the XML document structure to make a legitimate signature appear to cover attacker-controlled content. There are 8+ documented XSW variants. All exploit the same flaw: the SP validates the signature over one XML node, then processes a different XML node.
Example XSW:
<saml:Response>
<!-- Attacker's unsigned assertion (processed by vulnerable SP) -->
<saml:Assertion ID="attacker_assertion">
<saml:NameID>admin@victim.com</saml:NameID>
...
</saml:Assertion>
<!-- Legitimate signed assertion (signature validates) -->
<saml:Assertion ID="legit_assertion">
<ds:Signature><!-- Valid signature over this assertion --></ds:Signature>
<saml:NameID>attacker@evil.com</saml:NameID>
...
</saml:Assertion>
</saml:Response>
A vulnerable SP validates the signature on the second assertion but processes the first (unsigned) assertion, authenticating the attacker as admin@victim.com.
Defense: Use a SAML library that correctly implements XML signature validation -- do not write your own. Major libraries: python-saml (OneLogin), ruby-saml, passport-saml, spring-security-saml, and Microsoft's .NET SAML implementations. Keep them patched -- XSW vulnerabilities are periodically discovered.
SAML assertion replay:
An attacker who intercepts a SAML assertion (via network interception, log exposure, or XSS) can replay it within its validity window. Defenses: short NotOnOrAfter window (5 minutes maximum), SP-side assertion ID tracking to reject replayed IDs, HTTPS-only transmission of assertions.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
IdP Selection and Configuration
The Identity Provider choice determines your SSO capabilities, integration options, and operational model.
IdP comparison for enterprise SSO:
| IdP | Strength | Best For |
|---|---|---|
| Okta | Deep app catalog (7,000+ integrations), mature MFA, lifecycle management | Mid to large enterprise, multi-cloud |
| Microsoft Entra ID | Native M365/Azure integration, conditional access, Hybrid AD | Microsoft-centric organizations |
| Google Cloud Identity | Native Workspace integration, context-aware access | Google-centric organizations |
| Ping Identity | Complex federation scenarios, legacy system integration | Large enterprise with complex IAM |
| Keycloak | Open-source, self-hosted, highly customizable | Organizations requiring self-hosted IdP |
| JumpCloud | Cloud-native LDAP + SSO + MDM combined | SMB and cloud-first organizations |
Critical IdP configuration settings:
Session lifetime:
| Session Type | Recommended Duration |
|---|---|
| IdP session (web SSO) | 8 hours (re-auth at end of workday) |
| Persistent session (remember me) | 14 days maximum |
| API/service sessions | Per-token: 1 hour access token, 8 hour refresh |
| Admin sessions | 1 hour -- step-up MFA after timeout |
Step-up authentication:
Configure MFA step-up for sensitive applications -- users may have an IdP session but must re-authenticate with MFA to access high-risk apps:
- Finance/payroll applications
- Admin consoles
- Customer data systems
- Source code repositories
Okta: Policies > Authentication Policies > [App Policy] > Require additional factor Entra ID: Conditional Access > Named Locations + MFA required for specific apps
SAML attribute mapping:
Define what attributes the IdP sends in assertions. At minimum:
emailorNameID-- user identifiergroupsorroles-- group membership for authorization at the SPdisplayName-- friendly name for UI display
Avoid sending attributes the SP does not need -- principle of data minimization applies to SAML assertions.
Just-in-Time Provisioning and SCIM
SSO handles authentication; user provisioning is a separate concern. There are two approaches to creating user accounts in connected applications.
Just-in-Time (JIT) provisioning:
When a user authenticates via SAML for the first time, the SP creates their account based on attributes in the SAML assertion. No pre-provisioning step required.
Advantages: simple to configure; accounts are created on first login; always in sync with IdP at login time.
Disadvantages: accounts persist in the SP even when the user is removed from the IdP (they just cannot log in); groups/roles are only synced at login; deprovisioning requires manual cleanup or separate automation.
SCIM (System for Cross-domain Identity Management):
SCIM is a REST API standard (RFC 7644) for automated user lifecycle management. The IdP pushes user creates, updates, and deletes to the SP in real time.
Benefits over JIT:
- Users are deprovisioned in the SP immediately when removed from the IdP
- Group membership is synced continuously, not just at login
- Users can be provisioned before their first login (manager can pre-set up access)
SCIM 2.0 endpoints:
POST /Users-- create userPUT /Users/{id}-- replace user (full update)PATCH /Users/{id}-- partial update (disable user, update group)DELETE /Users/{id}-- deprovision
Most major IdPs (Okta, Entra ID, Ping) and SaaS applications (Salesforce, Workday, Slack, GitHub) support SCIM 2.0. Use SCIM wherever the SP supports it; fall back to JIT only when SCIM is unavailable.
Deprovisioning gap with JIT-only:
The most common access control failure in SSO implementations is the deprovisioning gap: a user is terminated and removed from the IdP, but their accounts persist in every application provisioned via JIT. An attacker who compromises the terminated employee's email (during the password reset window) or a PAM tool holding the session may still access these applications. SCIM closes this gap -- IdP deletion propagates to all SCIM-connected applications within seconds.
OIDC vs. SAML: When to Use Each
Modern applications increasingly support OIDC instead of (or alongside) SAML. Understanding the trade-offs determines which protocol to deploy.
Protocol comparison:
| Dimension | SAML 2.0 | OIDC |
|---|---|---|
| Token format | XML assertion | JSON/JWT |
| Transport | HTTP POST/Redirect (form-based) | OAuth 2.0 flows (redirect + token endpoint) |
| Primary use case | Web SSO to enterprise applications | Web + mobile + API authentication |
| Mobile/SPA support | Poor (XML/form redirect) | Excellent (OAuth 2.0 native) |
| Legacy app support | Excellent (supported since ~2005) | Growing (2014+) |
| API authorization | Not designed for it | Native (access tokens) |
| Complexity | Higher (XML, signatures) | Lower (JSON, JWT) |
Guidance:
- Use OIDC for: new applications, mobile apps, SPAs, APIs, microservices
- Use SAML for: legacy enterprise apps that only support SAML (Salesforce classic, older ERP systems), existing SAML integrations that work correctly, apps where SAML is the only supported protocol
- OIDC front-channel + SAML back-end: Many modern IdPs support OIDC-to-SAML translation -- your application speaks OIDC to the IdP, which speaks SAML to legacy SPs. This lets you modernize client-side without rearchitecting legacy SP integrations.
OIDC security considerations:
The OIDC security requirements are the same as OAuth 2.0 (covered in the OAuth/OIDC security guide):
- Enforce PKCE for all clients
- Validate ID token:
iss,aud,exp,nonce - Use state parameter to prevent CSRF
- Exact redirect_uri matching
- Short-lived access tokens + refresh token rotation
SSO Session Management and Logout
Session management is the most frequently overlooked aspect of SSO implementations.
Single Logout (SLO):
SAML Single Logout propagates a logout from one SP (or the IdP) to all connected SPs in the federation. Without SLO, logging out of one application leaves active sessions in all others -- an attacker who steals a session cookie for one app cannot pivot to others, but the user's sessions remain live and accessible to anyone with the cookie.
Implementing SLO correctly:
IdP-initiated SLO flow:
1. User clicks "Sign Out" in IdP dashboard
2. IdP sends LogoutRequest to each SP via SOAP back-channel or HTTP redirect
3. Each SP invalidates the session for this user
4. IdP sends LogoutResponse to the original SP
5. User is redirected to logout confirmation page
SP-initiated SLO: user logs out of an SP, SP sends LogoutRequest to IdP, IdP propagates to other SPs.
Most organizations do not implement SLO correctly -- they handle logout at the SP level only (invalidating the SP session) but leave the IdP session alive. The user can immediately re-authenticate without MFA.
Session timeout alignment:
SSO session lifetimes must be shorter than or equal to the IdP session lifetime. If the IdP session is 8 hours but the SP session is 24 hours, users can access the SP for 24 hours without re-authenticating with the IdP -- defeating the purpose of centralized session control.
Set SP session timeouts to trigger re-authentication with the IdP:
- Standard apps: 8 hours (align with work day)
- High-security apps: 1-2 hours with silent re-auth where possible
Session revocation for account compromise:
When an account is suspected compromised, administrators must be able to:
- Terminate the IdP session immediately (Admin Console > Users > [User] > Revoke all sessions)
- Propagate revocation to all connected SPs (via SCIM disable or SAML SLO)
- Reset MFA enrollments and recovery options
Document and test this workflow before it is needed. In an active compromise, speed matters.
The bottom line
SSO centralizes your identity attack surface -- every application you connect inherits the security of your IdP. Invest in your IdP configuration: enforce phishing-resistant MFA for all users (not just admins), use step-up authentication for sensitive applications, implement SCIM for real-time deprovisioning, and validate your SAML implementation with an XSW attack test. The organizations that benefit most from SSO treat the IdP as their most critical security control, not just an authentication convenience.
Frequently asked questions
What is the difference between SAML and OIDC for SSO?
SAML 2.0 is an XML-based protocol developed in the early 2000s primarily for web browser SSO between enterprise applications. It uses signed XML assertions transported via HTTP form POST or redirect. OIDC (OpenID Connect) is a JSON/JWT-based identity layer built on OAuth 2.0, developed in 2014. OIDC works natively for web, mobile, and API use cases. The practical guidance: use OIDC for all new applications; use SAML for legacy enterprise applications that only support SAML. Both can coexist -- modern IdPs like Okta and Entra ID support both protocols and can translate between them.
Is SSO a security risk because it creates a single point of failure?
SSO creates a single point of authentication -- but that is a security advantage, not a risk, when the IdP is properly hardened. With SSO, MFA enforcement, phishing-resistant credential policies, session controls, and account revocation all apply uniformly to every connected application. Without SSO, each application manages its own authentication, leading to inconsistent MFA enforcement, password reuse, and slow deprovisioning. The actual risk is misconfiguring the IdP -- leaving it without phishing-resistant MFA, with overly long session lifetimes, or with weak password policies. Harden the IdP and SSO reduces your attack surface.
What is an XML Signature Wrapping (XSW) attack?
XSW is a class of attacks against SAML implementations that exploit incorrect XML digital signature validation. An attacker who can intercept and modify a SAML response inserts a fraudulent, unsigned assertion element into the XML while keeping the legitimate signed assertion intact. A vulnerable SP validates the signature on the legitimate assertion but processes the attacker's unsigned assertion, granting the attacker access as an arbitrary user (including admin accounts). XSW attacks have affected multiple major platforms including Duo and several open-source SAML libraries. The defense is to use a well-maintained SAML library that explicitly validates which XML element the signature covers.
What is SCIM and why is it better than just-in-time provisioning?
SCIM (System for Cross-domain Identity Management) is a REST API standard for automated user provisioning and deprovisioning. The IdP pushes user lifecycle events (create, update, disable, delete) to connected applications in real time. Just-in-time (JIT) provisioning creates user accounts on first login but does not automatically deprovision them when the user is removed from the IdP. SCIM closes the deprovisioning gap: when a user is terminated and removed from the IdP, SCIM immediately disables or deletes their account in every connected application. This eliminates the window where a terminated employee's account remains accessible in downstream systems.
How do we handle applications that do not support SSO?
Applications that do not support SAML or OIDC require workarounds. Options: (1) Password vaulting in your IdP -- Okta, Entra ID, and others support 'form-based' SSO where the IdP injects credentials into web forms; the user logs in via SSO and the IdP provides the password transparently; (2) Enterprise password manager shared vault -- for applications requiring shared credentials (legacy admin consoles), store in a PAM or enterprise password manager with SSO-protected access; (3) Vendor pressure -- include SSO support as a requirement in vendor contracts and renewals; most modern SaaS vendors support SAML or OIDC. Applications that cannot integrate with your IdP should be treated as higher-risk and compensated with additional monitoring.
What is step-up authentication in SSO and when should we require it?
Step-up authentication requires users to re-authenticate with a stronger method (typically MFA) when accessing high-risk applications or performing sensitive operations, even if they already have an active SSO session. Use step-up for: financial systems (payroll, banking integrations), admin consoles, customer PII databases, source code repositories, and any system in scope for compliance frameworks (PCI, HIPAA). Configure at the IdP level using authentication policies (Okta: Authentication Policies; Entra ID: Conditional Access) -- the SP does not need to be modified. Step-up ensures that even if an attacker steals a session cookie for a low-risk application, they cannot use it to access high-risk systems without completing MFA.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, weekly, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals weekly.
The Mythos Brief is free.
AI that finds 27-year-old zero-days. What it means for your security program.
