The choice between SAML and OIDC can feel like navigating a dense forest of acronyms and specifications. Both protocols aim to solve the problem of single sign-on (SSO) and secure authentication, but they do so in different ways. This post aims to clear up the confusion by diving into practical scenarios where each protocol shines.

The Problem: Navigating Identity Federation

Imagine you’re building a platform that needs to integrate with multiple identity providers (IdPs). You need a way to authenticate users without managing their passwords directly. Enter SAML and OIDC. These protocols provide a standardized way to handle authentication and authorization, but choosing the right one depends on your specific use case.

SAML: The Workhorse of Enterprise SSO

SAML (Security Assertion Markup Language) has been around since 2002 and is widely used in enterprise environments. It’s particularly popular in scenarios where legacy systems are prevalent and integration with on-premises IdPs is required.

How SAML Works

SAML uses XML-based assertions to pass authentication and authorization data between parties. Here’s a simplified overview:

  1. User Access: The user tries to access a protected resource (Service Provider - SP).
  2. Redirection: The SP redirects the user to the IdP.
  3. Authentication: The IdP authenticates the user.
  4. Assertion: The IdP sends an XML assertion back to the SP, confirming the user’s identity and attributes.
  5. Access: The SP grants access based on the assertion.

Example SAML Configuration

Here’s a basic example of a SAML configuration using Okta as the IdP:

<!-- SAML Metadata for Service Provider -->
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://sp.example.com/metadata.xml">
    <SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.example.com/saml/acs" index="1"/>
    </SPSSODescriptor>
</EntityDescriptor>
⚠️ Warning: Ensure that your SAML assertions are signed and encrypted to prevent tampering.

Common Use Cases

  • Enterprise Applications: Integrating with on-premises applications like SAP, Salesforce, etc.
  • Legacy Systems: Where existing infrastructure relies heavily on XML-based configurations.
  • Compliance Requirements: When compliance with standards like NIST SP 800-63 is necessary.

Pros and Cons

ApproachProsConsUse When
SAMLWell-established, XML-based, integrates with legacy systemsVerbose, complex, harder to implementEnterprise apps, legacy systems, compliance requirements

🎯 Key Takeaways

  • SAML is robust for enterprise environments.
  • Use it when dealing with legacy systems.
  • Ensure strong security practices, especially with XML handling.

OIDC: The Modern Approach to SSO

OIDC (OpenID Connect) is built on top of OAuth 2.0 and provides a simpler, more modern approach to SSO. It’s JSON-based and easier to work with compared to SAML, making it a favorite among developers and DevOps teams.

How OIDC Works

OIDC follows these steps:

  1. User Access: The user tries to access a protected resource (RP - Relying Party).
  2. Authorization Request: The RP redirects the user to the IdP with an authorization request.
  3. Authentication: The IdP authenticates the user.
  4. Token Response: The IdP returns an ID token to the RP.
  5. Validation: The RP validates the ID token and grants access.

Example OIDC Configuration

Here’s a basic example of an OIDC configuration using Auth0 as the IdP:

# OIDC Configuration for Relying Party
issuer: https://auth.example.com
client_id: YOUR_CLIENT_ID
client_secret: YOUR_CLIENT_SECRET
redirect_uri: https://rp.example.com/callback
response_type: code
scope: openid profile email
🚨 Security Alert: Never expose client secrets in client-side code or public repositories.

Common Use Cases

  • Web and Mobile Applications: Where simplicity and ease of integration are crucial.
  • Cloud-Based Services: For modern applications hosted in the cloud.
  • Microservices Architecture: When integrating multiple services that require authentication.

Pros and Cons

ApproachProsConsUse When
OIDCJSON-based, easier to implement, supports modern architecturesLess mature in enterprise environmentsWeb apps, mobile apps, cloud services

🎯 Key Takeaways

  • OIDC is ideal for modern web and mobile apps.
  • Use it when working with cloud-based services.
  • Ensure secure handling of client secrets and tokens.

SAML vs OIDC: A Side-by-Side Comparison

Let’s break down the key differences and similarities between SAML and OIDC.

FeatureSAMLOIDC
Protocol TypeFederation ProtocolAuthentication Framework
Data FormatXMLJSON
Use CaseEnterprise, Legacy SystemsModern Web, Cloud
ComplexityHighLow
ScalabilityGoodExcellent
SecurityStrong, XML-basedStrong, JSON-based

When to Use SAML

  • Enterprise Integration: When integrating with on-premises enterprise applications.
  • Compliance Needs: When compliance with specific standards is required.
  • Legacy Systems: When working with older systems that rely on XML.

When to Use OIDC

  • Modern Applications: For web and mobile applications that benefit from simplicity.
  • Cloud Services: When deploying applications in cloud environments.
  • Microservices: When integrating multiple services that require authentication.
Best Practice: Choose the protocol that aligns best with your technology stack and organizational needs.

Real-World Examples

SAML in Action

Let’s walk through a real-world example of setting up SAML with Okta.

Step 1: Configure the Service Provider

Create a SAML app in Okta:

curl -X POST \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SSWS ${API_TOKEN}" \
  -d '{
    "name": "app.saml",
    "label": "My SAML App",
    "signOnMode": "SAML_2_0",
    "settings": {
      "signOn": {
        "audience": "https://sp.example.com",
        "recipient": "https://sp.example.com/saml/acs",
        "destination": "https://sp.example.com/saml/acs",
        "subjectNameIdTemplate": "${user.email}",
        "subjectNameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
        "responseSigned": true,
        "assertionSigned": true,
        "signatureAlgorithm": "RSA_SHA256",
        "digestAlgorithm": "SHA256",
        "honorForceAuthn": true,
        "authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
        "attributeStatements": [
          {
            "type": "EXPRESSION",
            "name": "email",
            "namespace": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
            "values": ["${user.email}"]
          }
        ]
      }
    }
  }' \
  "https://${OKTA_DOMAIN}/api/v1/apps"
Terminal
$ curl -X POST https://your-okta-domain/api/v1/apps -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: SSWS your-api-token" -d '{"name": "app.saml", "label": "My SAML App", "signOnMode": "SAML_2_0", "settings": {"signOn": {"audience": "https://sp.example.com", "recipient": "https://sp.example.com/saml/acs", "destination": "https://sp.example.com/saml/acs", "subjectNameIdTemplate": "${user.email}", "subjectNameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", "responseSigned": true, "assertionSigned": true, "signatureAlgorithm": "RSA_SHA256", "digestAlgorithm": "SHA256", "honorForceAuthn": true, "authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport", "attributeStatements": [{"type": "EXPRESSION", "name": "email", "namespace": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", "values": ["${user.email}"]}]} }}' { "id": "0oa1b2c3d4e5f6g7h8i9", "status": "ACTIVE", "name": "app.saml", "label": "My SAML App", ... }

Step 2: Configure the Identity Provider

Download the SAML metadata from Okta and configure your Service Provider accordingly.

Step 3: Test the Configuration

Log in to your Service Provider using the configured SAML app in Okta.

OIDC in Action

Now, let’s look at setting up OIDC with Auth0.

Step 1: Configure the Relying Party

Create an OIDC app in Auth0:

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -d '{
    "name": "my-oidc-app",
    "type": "spa",
    "connections": ["Username-Password-Authentication"],
    "callbacks": ["https://rp.example.com/callback"],
    "allowed_logout_urls": ["https://rp.example.com/logout"],
    "options": {
      "oidc_conformant": true
    }
  }' \
  "https://${AUTH0_DOMAIN}/api/v2/clients"
Terminal
$ curl -X POST https://your-auth0-domain/api/v2/clients -H "Content-Type: application/json" -H "Authorization: Bearer your-api-token" -d '{"name": "my-oidc-app", "type": "spa", "connections": ["Username-Password-Authentication"], "callbacks": ["https://rp.example.com/callback"], "allowed_logout_urls": ["https://rp.example.com/logout"], "options": {"oidc_conformant": true}}' { "client_id": "abc123def456ghi789jkl", "name": "my-oidc-app", "type": "spa", ... }

Step 2: Configure the Identity Provider

Set up the necessary scopes and claims in Auth0.

Step 3: Test the Configuration

Initiate the OIDC flow by redirecting to the Auth0 authorization endpoint.

Hybrid Approaches

It’s worth noting that SAML and OIDC can coexist in the same system. This is common in hybrid cloud environments where legacy systems require SAML while newer applications prefer OIDC.

Example: Combining SAML and OIDC

Let’s say you have a legacy application that requires SAML and a modern web app that uses OIDC. You can set up both protocols in your identity provider.

Step 1: Configure SAML for the Legacy App

Follow the steps outlined earlier to configure SAML in your IdP.

Step 2: Configure OIDC for the Modern App

Similarly, configure OIDC following the steps provided for OIDC setup.

Step 3: Manage Users and Attributes

Ensure that user attributes are correctly mapped and available for both protocols.

💜 Pro Tip: Use a unified user management system to simplify attribute mapping across different protocols.

Troubleshooting Common Issues

SAML Errors

Error: Invalid Signature

Cause: The SAML assertion signature is invalid.

Solution: Ensure that the signing certificate is correctly configured and valid.

Error: Audience Mismatch

Cause: The audience URI in the SAML assertion does not match the expected value.

Solution: Verify that the audience URI in the IdP matches the SP’s metadata.

OIDC Errors

Error: Invalid Client Secret

Cause: The client secret provided is incorrect.

Solution: Double-check the client secret and ensure it hasn’t expired or been revoked.

Error: Unauthorized Client

Cause: The client is not authorized to perform the requested action.

Solution: Verify that the client has the necessary permissions and is registered correctly in the IdP.

Conclusion

Choosing between SAML and OIDC comes down to understanding your specific requirements and constraints. SAML is a solid choice for enterprise environments and legacy systems, while OIDC offers a more modern, flexible approach suitable for web and mobile applications. By leveraging the strengths of each protocol, you can build a robust identity federation strategy that meets your organization’s needs.

📋 Quick Reference

  • curl -X POST https://auth.example.com/token - Request an access token from the IdP.
  • openssl verify -CAfile ca.crt saml_assertion.xml - Validate a SAML assertion signature.
  • auth0 login --domain your-auth0-domain - Log in to Auth0 for OIDC configuration.

That’s it. Simple, secure, works.