Note: I write this blog in English rather than Vietnamese because I primarily use it for personal knowledge documentation.
Single Sign-On (SSO) is like a master key for the digital world, allowing users to access multiple applications with just one login. As we discussed previously, SSO streamlines authentication, enhances security, and simplifies user management. At the heart of many SSO implementations lies SAML—Security Assertion Markup Language—a robust, open standard that enables secure exchange of authentication and authorization data. This blog dives into SAML’s role in SSO, how to implement it effectively, and the critical security measures needed to ensure a secure and seamless experience.
Why SAML for SSO?
Before SSO, users juggled separate credentials for each application, leading to password fatigue and security risks. SSO solves this by centralizing authentication: users log in once via a trusted system and gain access to all authorized services. SAML is a cornerstone standard for this process, particularly in enterprise environments where secure, cross-domain authentication is essential. It acts as a universal language, allowing systems to communicate user identities and permissions securely.
The Key Players in SAML
SAML involves three main roles:
- The Principal: The user seeking access to an application.
- The Identity Provider (IdP): The centralized authentication hub (e.g., Okta, Microsoft Entra ID, Google Workspace) that verifies the user’s identity and shares access details.
- The Service Provider (SP): The application the user wants to access (e.g., Salesforce, Box, or internal tools), which relies on the IdP for authentication.
SAML serves as the secure bridge, enabling these parties to coordinate authentication.
How SAML Works: The Authentication Flow
SAML uses XML-based messages called SAML assertions to share user information, including identity, authentication status, and permissions. There are two primary SAML flows:
- IdP-Initiated Flow: The user starts at the IdP’s portal, logs in, and selects an application. The IdP sends a SAML response to the SP, granting access without a prior request.
- SP-Initiated Flow: The user accesses the SP directly. If unauthenticated, the SP redirects them to the IdP with a SAML request. The IdP authenticates the user and sends a SAML response to the SP’s Assertion Consumer Service (ACS) endpoint.
In the SP-initiated flow, the SAML request includes the SP’s entity ID, the ACS URL, a unique request ID, and a timestamp. The SAML response contains corresponding details, user data (via NameID), attributes (e.g., email, role), validity conditions (e.g., time window), and is signed with XML signatures for security. The Relay State ensures users return to their intended SP resource after authentication by preserving the original URL.
Implementing SAML: A Step-by-Step Guide
Implementing SAML requires careful configuration of both the IdP and SP, robust handling of SAML messages, and strict security measures to prevent vulnerabilities. Below is a detailed guide to setting up SAML-based SSO.
1. Establish SAML Trust
To enable secure communication, the IdP and SP must establish a trust relationship by sharing:
- Entity IDs: Unique identifiers (often URLs) for the IdP and SP.
- Signing Certificates: Public keys to validate SAML message signatures.
- Endpoint URLs: The IdP’s login URL and the SP’s ACS URL.
Metadata simplifies this process. Both parties provide an XML file (or URL) containing entity IDs, certificates, endpoints, and supported bindings (e.g., HTTP-POST). For example, an IdP like Okta might provide a metadata URL (e.g., https://your-org.okta.com/app/saml/metadata
), which the SP imports to auto-configure trust. If metadata isn’t available, manually exchange these details.
Practical Steps:
- SP: Import the IdP’s metadata into the application’s SAML settings (e.g., via an admin portal or configuration file like
saml.config
). - IdP: Add the SP as a trusted application, uploading its metadata or entering its ACS URL and entity ID.
- Rotate certificates periodically (e.g., every 1–2 years) to avoid expired certificate issues.
2. Configure SAML Flows
Choose between IdP-initiated or SP-initiated flows (SP-initiated is more common, as users often access applications directly).
IdP Configuration:
- Enable SAML for the SP in the IdP’s admin console (e.g., Okta, Microsoft Entra ID).
- Specify the SP’s ACS URL, entity ID, and attribute mappings (e.g., NameID, email, role).
- Set the binding to HTTP-POST for security (it sends data in the request body, unlike HTTP-Redirect).
- Ensure the SAML response is signed with the IdP’s private key.
SP Configuration:
- Enable SAML authentication in the SP’s settings (e.g., Salesforce’s SSO settings).
- Import the IdP’s metadata or manually enter its entity ID, login URL, and certificate.
- Define the ACS URL (e.g.,
https://your-app.com/saml/acs
). - For SP-initiated flows, configure the SP to generate SAML requests with the correct issuer and ACS URL.
- Use tools like Okta’s SAML validation tool or browser extensions (e.g., SAML Chrome Panel) to test the flow.
3. Implement the Assertion Consumer Service (ACS)
The ACS is the SP’s endpoint (e.g., /saml/acs
) that receives and processes the SAML response. It’s the most critical component, as flawed validation here is the primary source of SAML vulnerabilities.
Implementation Steps:
- Set up the ACS to handle HTTP POST requests containing the SAML response.
- Parse the XML response to extract assertions (e.g., NameID, attributes, conditions).
- Verify signatures using the IdP’s public certificate.
- Map attributes to the SP’s user profile, supporting Just-in-Time (JIT) provisioning if enabled.
- Use the Relay State to redirect users to their intended resource.
- Create a user session (e.g., via a session cookie) upon successful validation.
4. Handle Provisioning (Optional)
SAML focuses on authentication but often integrates with provisioning to manage user profiles:
- Just-in-Time (JIT) Provisioning: The SP creates or updates user accounts based on SAML attributes (e.g., creating a new user if none exists).
- Real-Time Provisioning: Use standards like SCIM to sync profiles between IdP and SP proactively.
- Decide whether the SP uses SAML attributes for authentication only or for provisioning too.
5. Test and Validate
- Use tools like Okta’s SAML Validation Tool or SAML-tracer to inspect messages.
- Test both flows, edge cases (e.g., expired certificates, invalid signatures), and provisioning.
- Monitor ACS logs for validation failures, ensuring sensitive data isn’t logged.
6. Leverage Toolkits
Use SAML libraries to simplify implementation:
- Golang:
crewjam/saml
,russellhaering/gosaml2
. - Python:
python3-saml
,pysaml2
. - Java: Spring Security SAML, OpenSAML.
- PHP: SimpleSAMLphp.
- Node.js: Passport-SAML. IdPs like Okta provide toolkits and validation tools to streamline setup.
SAML Security: Critical Best Practices
SAML is highly secure when implemented correctly, but misconfigurations can lead to exploits like unauthorized access or session hijacking. The ACS is the primary attack surface, so robust validation is essential. Follow these best practices:
- Restrict XML Parsers: Use a minimal parser and disable features like DTD fetching to prevent XML External Entity (XXE) attacks, which could enable DDoS, remote code execution, or file disclosure.
- Canonicalize XML: Normalize XML using a standard algorithm (C14N) to prevent manipulation via comments or whitespace that could bypass signature validation.
- Validate XML Schema: Reject non-compliant SAML to block XML Signature Wrapping (XSW) attacks, where malicious XML is added outside signed elements.
- Verify All Signatures: Ensure every assertion is signed and validated using the IdP’s certificate. Reject partially signed responses.
- Limit Signature Algorithms: Accept only secure algorithms (e.g., RSA-256) and reject insecure ones (e.g., “none”).
- Enforce HTTPS: Transmit all SAML messages over HTTPS to prevent interception.
- Validate Parties: Confirm the
issuer
,destination
,audience
, andrecipient
match expected values from the trust configuration. - Enforce Time Windows: Reject responses outside the
NotBefore
andNotOnOrAfter
timestamps, accounting for clock skew (e.g., ±5 minutes). - Prevent Replay Attacks: Cache SAML response IDs and reject duplicates within the validity window.
- Limit Buffer Size: Restrict XML parser buffers to prevent DDoS via oversized payloads.
SAML vs. Alternatives
While SAML excels in enterprise settings, alternatives like OpenID Connect (OIDC) (built on OAuth) are popular for their JSON-based simplicity, especially in mobile and microservices architectures. SAML is like SOAP—robust but complex—while OIDC is like REST, modern and lightweight. WS-Federation is another option, common in Microsoft ecosystems. SAML remains ideal for scenarios requiring strong identity federation, such as enterprise.
Conclusion
SAML is a powerful standard for implementing enterprise-grade SSO, enabling secure, seamless access across applications. By establishing trust, configuring flows, implementing a robust ACS, and following stringent security practices, developers can create a reliable SSO solution. Tools and libraries from providers like Okta simplify the process, while thorough testing ensures success. When implemented correctly, SAML transforms authentication into a true digital master key, balancing user convenience with top-tier security.
Reference
https://learn.microsoft.com/vi-vn/entra/architecture/auth-saml
https://www.okta.com/blog/2020/09/what-is-saml/
https://www.youtube.com/watch?v=4ULlJEupV-I