New, Stytch for Fraud & Risk PreventionLearn more
back arrow
Back to blog

What are SAML assertions?

Auth & identity
August 22, 2024
Author: Isaac Ejeh
Author: Edwin Lim
hero-image

A SAML assertion is an XML-based data structure that conveys authentication and authorization information between an identity provider (IdP) and a service provider (SP) within a SAML SSO authentication flow. SAML assertions typically contain statements and nested attributes about a user that an IdP must have authenticated, and other relevant details about the authentication event.

These statements contain attributes that define the user’s identity, their authentication status, the time and method of authentication, conditions that specify when and where the assertion is valid, and other relevant user-specific attributes like role or department affiliations. This way, service providers can rely on assertions to make access control decisions within their systems, without directly authenticating any user.

In this article, we’ll explore the XML structure and lifecycle of SAML assertions and analyze how they’re used in authentication and authorization scenarios. You’ll also learn about the possible errors you might encounter when working with SAML assertions, and how to debug and troubleshoot these errors.

What are SAML responses, and how are they different from SAML assertions?

A SAML response is an XML document that delivers one or more SAML assertions from an identity provider (IdP) to a service provider (SP), along with other necessary protocol-related information. To understand this relationship, think of a SAML response as an envelope containing a letter—the envelope (response) holds and delivers the letter (assertion), which contains the actual information being sent.

While the SAML assertion is the core message containing authentication and authorization details, the SAML response provides the overall structure and context for the assertion(s). In addition to the assertion(s), SAML responses typically include:

  • A unique ID for the response.
  • The issue instant (timestamp).
  • The destination URL.
  • Status information (success or error messages).
  • A digital signature that verifies the integrity and authenticity of the entire response.

Here’s an example XML structure of a signed SAML response, but without a SAML assertion:

<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response 
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    ID="_response123456789"
    Version="2.0"
    IssueInstant="2024-08-04T12:34:56Z">

    <saml:Issuer>https://idp.example.com</saml:Issuer>
    
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
        <!-- Optional: <samlp:StatusMessage>...</samlp:StatusMessage> -->
    </samlp:Status>
    
    <saml:Assertion
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
        ID="_assertion123456789"
        Version="2.0"
        IssueInstant="2024-08-04T12:34:56Z">
        <!-- An assertion can go in here -->
    </saml:Assertion>

    <!-- Optional: Additional assertions can be included here -->

    <ds:Signature>
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
            <ds:Reference URI="#_response123456789">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <ds:DigestValue>base64digestvalue==</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>base64signaturevalue==</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIID...base64cert...DQYJKoZIhv</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>

</samlp:Response>

This structure makes it possible for the SAML response to handle multiple assertions if needed, provide status messages, and add an extra layer of security and context to the communication between the IdP and SP.

The XML structure of a SAML assertion

SAML assertions are built upon a well-defined XML structure that’s designed to be flexible and extensible. This structure makes it possible for assertions to carry all the authentication and authorization details required by a service provider to make informed access control decisions about users.

Nested structure of a SAML response and assertion in XML format

The key elements that make up a SAML assertion include:

  • Assertion ID: A unique identifier for the assertion.
  • Issuer: Information about the identity provider that created the assertion.
  • Signature: A digital signature to ensure the integrity and authenticity of the assertion.
  • Subject: Details about the authenticated user which the assertion is about.
  • Conditions: Criteria that must be met for the assertion to be considered valid.
  • Statements: The core content of the assertion, including authentication, attribute, and authorization decision information.

These elements collectively provide a detailed description of the user and the context of their authentication, ensuring that the assertion is secure, properly structured, and parsable by service providers.

Assertion ID

The Assertion ID is a unique identifier assigned to each SAML assertion by the issuing IdP. It ensures that each assertion can be distinctly referenced, which helps to differentiate it from other assertions when parsed by an SP. This unique ID also plays a crucial role in preventing replay attacks by ensuring that the same assertion cannot be reused maliciously.

For example, if an attacker attempts to intercept and reuse a particular assertion, an SP would be able to detect that the assertion ID has already been used if it checks against its record of previously processed assertions. This prevents the attacker from successfully reusing the assertion to gain unauthorized access.

<saml:Assertion ID="_93af655219464fb403b34436cfb0c5cb1d9a5502" 
               IssueInstant="2024-08-04T12:34:56Z" 
               Version="2.0">
  </saml:Assertion>

Issuer

The Issuer element specifies the identity provider that generated and issued the SAML assertion. This element helps service providers verify the source of an assertion and ensure it originates from an IdP with which it has an established relationship.

<saml:Issuer>https://idp.example.com</saml:Issuer>

Signature

The Signature element ensures the integrity and authenticity of a SAML assertion. It contains cryptographic information, including a digital signature, which allows the service provider to verify that the assertion hasn’t been altered and that it indeed originates from the specified Issuer (IdP). The signature typically covers the entire assertion and includes components such as the SignatureMethod, SignatureValue, DigestValue, KeyInfo, and more, all of which are specified using XML signature standards (XML-DSig).

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <ds:Reference URI="#_93af655219464fb403b34436cfb0c5cb1d9a5502">
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>base64digestvalue==</ds:DigestValue>
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>base64signaturevalue==</ds:SignatureValue>
    <ds:KeyInfo>
        <ds:X509Data>     
            <ds:X509Certificate>MIID...base64cert...DQYJKoZIhv</ds:X509Certificate>
        </ds:X509Data>
    </ds:KeyInfo>
</ds:Signature>

Subject

The Subject element contains information about the authenticated user. It typically includes a unique identifier for the user (represented by a NameID) and may also contain additional information that specifies the method of confirmation (represented by the SubjectConfirmation element).

<saml:Subject>
  <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.com</saml:NameID>
  <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
    <saml:SubjectConfirmationData 
      InResponseTo="abcdef12345" 
      Recipient="https://sp.example.com/saml2/acs" 
      NotOnOrAfter="2024-09-04T12:34:56Z"/>
  </saml:SubjectConfirmation>
</saml:Subject>

Conditions

The Conditions element specifies the constraints or circumstances under which the assertion is considered valid. This can include a validity period (NotBefore and NotOnOrAfter timestamps) and other constraints such as the intended audience for the assertion. This ensures the assertion is only used according to the intended context and timeframe.

<saml:Conditions NotBefore="2024-08-04T12:00:00Z" NotOnOrAfter="2024-08-04T13:00:00Z">
  <saml:AudienceRestriction>
    <saml:Audience>https://sp.example.com</saml:Audience>
  </saml:AudienceRestriction>
</saml:Conditions>

Statements

SAML assertions contain one or more statement elements that provide specific information about the authenticated user. These include authentication statements, attribute statements, and authorization decision statements.

  • AuthenticationStatement: Affirm that a user has been authenticated and provide details about the authentication method used.
  • AttributeStatement: Contains attributes about the user, such as their name, email, role, and department.
  • AuthorizationDecisionStatement: Specifies the actions or resources that the user has been authorized to access.

Types of SAML assertion statements

Authentication assertion statements

Service providers use the AuthenticationStatement to verify that a user has been authenticated by the SAML identity provider. They also use this statement to determine the strength of the authentication method in order to make informed decisions about whether to grant access or require additional authentication. The key elements contained in an authentication statement include:

  • AuthnInstant: Specifies the exact time when the user authentication took place.
  • AuthnContext: Describes the authentication mechanism used (e.g., password, biometrics, token, magic links).
  • SessionIndex: Is an optional attribute that references the specific authentication session.
<saml:AuthnStatement 
  AuthnInstant="2024-08-04T12:30:00Z"
  SessionIndex="_abc4567890">
  <saml:AuthnContext>
    <saml:AuthnContextClassRef>
      urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    </saml:AuthnContextClassRef>
  </saml:AuthnContext>
</saml:AuthnStatement>

Attribute assertion statements

AttributeStatements contain one or more attribute elements, which are essentially name-value pairs that describe specific characteristics or properties of the user. These attributes are used to convey additional information about the user that may be relevant to the service provider for authorization decisions or other purposes.

<saml:AttributeStatement>
  <saml:Attribute Name="role">
    <saml:AttributeValue>admin</saml:AttributeValue>
  </saml:Attribute>
  <saml:Attribute Name="email">
    <saml:AttributeValue>user@example.com</saml:AttributeValue>
  </saml:Attribute>
  <saml:Attribute Name="department">
    <saml:AttributeValue>Engineering</saml:AttributeValue>
  </saml:Attribute>
</saml:AttributeStatement>

Authorization decision statements

AuthorizationDecisionStatements determine whether an authenticated user is allowed to access specific resources and the kind of actions they’re authorized to perform. An AuthorizationDecisionStatement typically includes the following key elements:

  • Resource: The URI of the resource that an authenticated user is allowed to access.
  • Decision: The authorization decision (e.g., Permit, Deny, or Indeterminate).
  • Action: The action that the user can perform on the resource.
  • Evidence: Optional information supporting the user authorization decision.

However, it's important to note that AuthorizationDecisionStatements may not be as frequently used in SAML compared to Authentication and AttributeStatements. Most service providers would prefer to handle authorization decisions locally rather than relying on pre-determined decisions from an identity provider.

<saml:AuthzDecisionStatement
  Resource="https://example.com/protected-resource"
  Decision="Permit">
  <saml:Action>read</saml:Action>
  <saml:Evidence>
    <!-- Additional evidence supporting the decision -->
  </saml:Evidence>
</saml:AuthzDecisionStatement>

Comprehensive XML structure of a SAML assertion

As we’ve established so far, a comprehensive SAML assertion could contain all the key elements we just went over, including the Assertion ID, Signature, Issuer, Subject, Conditions, and the three types of assertion statements (Authentication, Attribute, and Authorization Decision Statements).

These components collectively form the structure of a SAML assertion, providing a secure and extensible way to communicate identity and authorization data between IdPs and SPs in SAML SSO authentication flows.

Here’s a comprehensive structure of a SAML assertion in XML, combining all the elements:

<?xml version="1.0" encoding="UTF-8"?>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                ID="_93af655219464fb403b34436cfb0c5cb1d9a5502"
                Version="2.0"
                IssueInstant="2024-08-04T12:34:56Z">
    
    <saml:Issuer>https://idp.example.com</saml:Issuer>
    
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
            <ds:Reference URI="#_93af655219464fb403b34436cfb0c5cb1d9a5502">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <ds:DigestValue>base64digestvalue==</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>base64signaturevalue==</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>     
<ds:X509Certificate>MIID...base64cert...DQYJKoZIhv</ds:X509Certificate></ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    
    <saml:Subject>
        <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.com</saml:NameID>
        <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <saml:SubjectConfirmationData 
                InResponseTo="abcdef12345" 
                Recipient="https://sp.example.com/saml2/acs" 
                NotOnOrAfter="2024-09-04T12:34:56Z"/>
        </saml:SubjectConfirmation>
    </saml:Subject>
    
    <saml:Conditions NotBefore="2024-08-04T12:00:00Z" NotOnOrAfter="2024-08-04T13:00:00Z">
        <saml:AudienceRestriction>
            <saml:Audience>https://sp.example.com</saml:Audience>
        </saml:AudienceRestriction>
    </saml:Conditions>
    
    <saml:AuthnStatement 
        AuthnInstant="2024-08-04T12:30:00Z"
        SessionIndex="_abc4567890">
        <saml:AuthnContext>
            <saml:AuthnContextClassRef>
                urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
            </saml:AuthnContextClassRef>
        </saml:AuthnContext>
    </saml:AuthnStatement>
    
    <saml:AttributeStatement>
        <saml:Attribute Name="role">
            <saml:AttributeValue>admin</saml:AttributeValue>
        </saml:Attribute>
        <saml:Attribute Name="email">
            <saml:AttributeValue>user@example.com</saml:AttributeValue>
        </saml:Attribute>
        <saml:Attribute Name="department">
            <saml:AttributeValue>Engineering</saml:AttributeValue>
        </saml:Attribute>
    </saml:AttributeStatement>
    
    <saml:AuthzDecisionStatement
        Resource="https://example.com/protected-resource"
        Decision="Permit">
        <saml:Action>read</saml:Action>
        <saml:Evidence>
            <!-- Additional evidence supporting the decision -->
        </saml:Evidence>
    </saml:AuthzDecisionStatement> 
</saml:Assertion>

The lifecycle of a SAML assertion

There are five distinct stages that a SAML assertion must undergo, right from when it’s generated by an identity provider (IdP) to when it’s consumed by a service provider (SP), or even considered expired or invalidated.

Stage 1: Generating a SAML assertion

SAML assertions are generated by an IdP after a user successfully authenticates their IdP-provisioned credentials via the SP-initiated SAML SSO flow, or selects the SP from a list of SAML-configured apps provided by the IdP via the IdP-initiated SAML SSO flow. The IdP constructs the assertion’s XML structure by encapsulating attributes about the user and the authentication event. It also signs the assertion to ensure its integrity using XML signatures. Once generated, the assertion is ready for transmission to the SP.

Stage 2: Transporting the assertion

Once a SAML assertion is generated, it has to be transmitted from the IdP to the SP that needs it to make a decision. This transmission often occurs via an HTTP Redirect or POST binding, where the assertion is securely sent in a browser response or directly through an HTTP request. The assertion is typically included in a SAML response message that the identity provider sends to the SP’s Assertion Consumer Service (ACS) URL.

Stage 3: Validating the assertion

Upon receiving the SAML assertion, the service provider has to perform a series of validation checks to ensure its authenticity and integrity. This involves verifying the digital signature of the assertion to confirm it was issued by a legitimate IdP, and that it hasn’t been tampered with during transmission. The SP also checks the assertion’s validity period, ensuring it falls within the specified time range and hasn’t expired.

Stage 4: Consuming the assertion

At this point, the SP proceeds to consume the assertion after it passes all validation checks. This involves extracting the user’s attributes and any additional information contained within the assertion. The SP then utilizes this information to make authorization decisions, such as granting user access to protected resources or personalizing the user’s experience. Once an assertion has been consumed, it’s typically logged and then discarded to prevent reuse and replay attacks.

Stage 5: Expiration and revocation of the assertion

Every SAML assertion has a predefined validity period, which is defined by the NotOnOrAfter condition and specified in the assertion itself. Once this validity period expires, the assertion is automatically considered invalid. However, in certain scenarios, an assertion might need to be invalidated or revoked before its expiration time. This could happen due to security breaches or changes in user permissions. The IdP can invalidate an assertion by updating its status or issuing a revocation notification to the SP.

Dealing with SAML assertion errors?

SAML assertion errors can be a pain, but they’re an important security feature. These are issues that can occur during the processing or validation of a SAML assertion. They indicate problems such as expired assertions, invalid signatures, mismatched recipient information, or violations of assertion conditions.

As such, when a service provider encounters these errors, it typically rejects the assertion and denies access to the user. These errors are crucial for maintaining the integrity and security of the authentication process, preventing unauthorized access attempts, and helping system administrators identify and resolve configuration issues in both identity providers and service providers.

Common SAML assertion errors include:

  1. Format and schema errors: This error can occur if an assertion doesn’t conform to the SAML XML schema or if required elements are missing or incorrectly formatted.
  2. Incorrect assertion issuer: This error occurs when the Issuer of the assertion doesn't match the expected identity provider. This could indicate an IdP configuration issue or a potential IdP impersonation.
  3. Signature validation errors: This error occurs when the signature on a SAML assertion can’t be verified. This can be due to an invalid or missing signature, or if the certificate used to sign the assertion isn’t trusted or has expired.
  4. Missing or invalid subject: This error can occur if the assertion doesn't properly identify the user. This means that the Subject element is missing or doesn't contain the expected user information.
  5. Subject confirmation errors: This error can occur if the Recipient attribute in the SubjectConfirmationData doesn't match the SP's endpoint URL, if the InResponseTo attribute doesn't match the ID of the original SAML request sent by the SP, or if the Method attribute specifies a confirmation method that isn’t supported by the SP.
  6. Expired assertion errors: Assertions have specific validity periods defined by the NotBefore and NotOnOrAfter conditions they contain. If the assertion is used outside this time frame, it will be rejected due to expiration.
  7. Audience restriction errors: SAML assertions contain an AudienceRestriction element that specifies the service provider that can accept the assertion. If the audience restriction doesn’t match the expected entity ID of the service provider, the assertion will be rejected. This error prevents assertions from being used by unintended recipients.

Best practices for debugging and troubleshooting SAML assertion errors

1. Double-check metadata configuration: Incorrect or mismatched metadata configuration can cause communication failures between an IdP and SP. It’s important to regularly verify that the metadata for both the IdP and SP is up-to-date and correctly configured. This includes checking entity IDs, endpoints, certificates, and supported bindings.

2. Verify time synchronization between IdP and SP: Time-related issues are another common source of assertion validation errors. You have to ensure that the clocks on your IdP and SP servers are synchronized using a reliable time source, such as an NTP server. This is highly important because SAML assertions often contain time-based validity conditions, and even small time discrepancies can lead to rejected assertions. As such, always confirm that the assertion’s IssueInstant, NotBefore, and NotOnOrAfter timestamps are correct and within the expected range.

3. Use SAML-tracer or similar browser extensions: Browser extensions like SAML-tracer can capture and decode SAML messages (both requests and responses) in real-time. This allows you to inspect the raw SAML assertions and responses as they’re being sent, making it easier to identify issues with formatting, missing attributes, or incorrect values, whether it’s via an SP-initiated or IdP-initiated SAML flow.

4. Implement proper error handling and logging: Ensure your application has implemented robust error handling that captures and logs SAML-related errors in detail. This should include the full error message, stack trace, and relevant SAML message contents (with sensitive information properly masked). Proper error-logging practices make it much easier to diagnose issues when they occur in production environments.

5. Verify assertion signature: Always ensure that the certificates used to sign an assertion are valid, trusted, and not expired. You can also verify if the signature matches the assertion content using XML signature validation tools.

6. Use a SAML validator tool: There are several online SAML validation tools that can help you verify the structure, signature, and content of your SAML assertions for free. These tools can check for XML validity, proper formatting, and adherence to SAML standards. By pasting your SAML assertion into a validator, you can quickly identify syntax errors or required elements that are missing.

7. Use network analysis tools: Tools like Wireshark can help you analyze the network traffic between an IdP and SP. This can be particularly useful for identifying issues with SSL/TLS connections, HTTP redirects, or other network-level problems that might be interfering with the SAML authentication process. As such, examining raw network traffic can reveal issues that might not be captured in application-level logs.

Implementing SAML SSO using Stytch

Building a custom SAML implementation from scratch is a Herculean task. It requires a deep understanding of the SAML protocol, and we've only scratched the surface in this article.

Based on feedback from our customers who have migrated off in-house implementations of the SAML protocol, we strongly caution against building SAML all by yourself. The SAML protocol is complex, and as such, it’s easy to overlook security vulnerabilities that could potentially compromise your infrastructure in production.

At Stytch, we offer robust APIs and SDKs that make it super easy to support SAML SSO in your SaaS applications, often within weeks or even days. We act as an intermediary that standardizes the SAML authentication process across multiple identity providers.

SAML SSO architecture using Stytch as auth provider

These IdPs are responsible for authenticating users and issuing SAML assertions, while Stytch facilitates the connection between the IdPs and SPs, forwarding XML requests and assertions between both parties.

As a B2B SaaS provider, you can easily configure SAML for your enterprise customers, regardless of the identity provider they use within their organization. We handle the complexities of routing AuthnRequests to the appropriate IdP and relaying SAML responses back to your application, allowing you to focus on your core business logic.

Ready to implement SAML SSO in your SaaS app using Stytch? Check out our SAML Docs and sign up for a free developer account.

If you have any questions regarding our features or pricing, feel free to reach out to us at support@stytch.com or schedule a call with one of our Solutions Engineers.

cta image

Build SSO with Stytch

cta image

Share

LinkedIn share
Twitter share
Facebook share