SAML Authentication — Complete Enterprise SSO Guide
In this tutorial, you will learn about SAML Authentication. We cover key concepts, practical examples, and best practices to help you master this topic.
Security Assertion Markup Language (SAML) is an XML-based framework for exchanging authentication and authorization data between identity providers and service providers. It is the dominant standard for enterprise single sign-on.
What You'll Learn
You'll learn how SAML works, the difference between SAML and OIDC, and how to implement SAML-based authentication.
Why It Matters
SAML is required for enterprise integrations with platforms like Salesforce, Workday, AWS SSO, and most corporate identity systems (ADFS, Okta, OneLogin).
Real-World Use
A large enterprise uses ADFS as its SAML identity provider. Employees log into their corporate portal and access dozens of SAML-enabled SaaS applications without re-entering credentials.
sequenceDiagram
participant User
participant SP as Service Provider
participant IDP as Identity Provider
User->>SP: Access Resource
SP->>User: Redirect to IDP (SAML Request)
User->>IDP: Authenticate
IDP->>User: SAML Response (Assertion)
User->>SP: POST SAML Response
SP->>SP: Validate Assertion
SP->>User: Access Granted
Teacher's Mindset
SAML is like an embassy-issued visa. The embassy (IDP) verifies your identity and issues a document (SAML assertion) that other countries (service providers) accept because they trust the embassy.
Implementation
from flask import Flask, request, jsonify
from onelogin.saml2.auth import OneLogin_Saml2_Auth
app = Flask(__name__)
def init_saml_auth(req):
auth = OneLogin_Saml2_Auth(req, custom_base_path="/path/to/saml/settings")
return auth
@app.route("/api/saml/login")
def saml_login():
req = prepare_flask_request(request)
auth = init_saml_auth(req)
return redirect(auth.login())
@app.route("/api/saml/acs", methods=["POST"])
def saml_acs():
req = prepare_flask_request(request)
auth = init_saml_auth(req)
request_id = None
auth.process_response(request_id=request_id)
errors = auth.get_errors()
if errors:
return jsonify({"error": errors}), 400
if auth.is_authenticated():
attributes = auth.get_attributes()
name_id = auth.get_nameid()
return jsonify({
"name_id": name_id,
"attributes": attributes
})
return jsonify({"error": "Not authenticated"}), 401
Common Mistakes
| Mistake | Fix |
|---|---|
| Not validating SAML response signature | Always verify the XML signature |
| Accepting unsigned assertions | Require signing for all SAML assertions |
| Missing audience restriction | Validate AudienceRestriction matches your SP |
| Clock skew issues | Allow 5-minute clock skew in validation |
| Replay attacks without assertion expiry | Validate NotBefore and NotOnOrAfter conditions |
Practice Questions
- What is the difference between SAML and OIDC?
- What is an identity provider in SAML?
- What is a SAML assertion?
- How does SAML prevent replay attacks?
- What is the difference between SP-initiated and IDP-initiated SSO?
Challenge
Set up a SAML service provider using python3-saml or similar library. Configure it with a test IDP (like SSOCircle or a local Keycloak instance). Complete the full SSO flow.
FAQ
Mini Project
Set up Keycloak as a SAML IDP. Register a Python Flask service provider. Implement SP-initiated SSO with signed assertions. Test with valid and tampered assertions.
What's Next
Learn about API keys for simple service-to-service authentication.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro