Last updated at Tue, 25 Apr 2023 21:40:15 GMT

It seems like Security Assertion Markup Language (SAML) is everywhere in the enterprise landscape these days, from Google, Microsoft, and Auth-0 to Okta and Secret Double Octopus. However, despite its ubiquity, it is not commonly understood, leading to misconceptions, misconfigurations, frustrations, and in some cases, the complete abandonment of the solution (and the many benefits it provides).

SAML solves two major goals in the security landscape. First, user authentication information is never transmitted through or stored by third-party services (which is huge!). And second, users are presented with a single sign-on experience regardless of which service they are logging in to (and in many instances don’t have to specifically log in to the service at all).

In this blog, we will take a deep dive into everything you need to know about SAML.

What is SAML?

So, let’s start with the name: Security Assertion Markup Language. Like most things named “X Markup Language,” SAML is based on XML. The other half of the name very accurately describes SAML’s purpose of allowing one system to assert a user’s identity to another system, after verifying their identity, of course.

You’ll notice that the name does not contain “web,” “internet,” or “SSO.” While these are the most common use cases of SAML, they are by no means the only uses. At its core, SAML is a general framework independent of any particular use case or technology, which presents both advantages and disadvantages. Being general, it can be used in many scenarios, but its flexibility means configuration can be difficult, since different implementations make different assumptions. It also means that the raw configuration has a lot of boilerplate in it to configure SAML for Web SSO.

Components of SAML

Identity provider (IdP)

An IdP is responsible for authenticating the user and can also be responsible for authorization, though this is less common. Typical examples of IdPs include Azure Active Directory, ADFS, Okta, Auth-0, G Suite, and GLUU. Most (if not all) implement SAML as one of many authentication mechanisms they offer, and many of these solutions link to one or more backend systems to actually authenticate the user. They also add alternatives and additional authentication requirements in addition to the backend authentication, such as two-factor authentication. Some solutions, like Secret Double Octopus, do away with traditional authentication altogether.

Service provider (SP)

The SP provides services to the end user, such as email, word processing, sales management, and enterprise resource planning. Before SSO capabilities came along, each of these systems had to provide authentication services themselves, either by integrating into a backend system like Active Directory or using a built-in user database. Most of these options are either ill-suited to a web-based environment (like Kerberos) or required the username/password to pass through the SP systems.

Metadata

Both IdPs and SPs utilize metadata that describes both of them. This metadata forms the core of the trust relationship between the two components. Remember how SAML is a general solution? Well, the metadata contains more than just trust information, but also communication information describing how the SP and IdP will exchange assertions. This includes both a destination and a technology. With web-based SSO, this is a URL, and the method is HTTP Post performed via the client web browser. Many common IdPs today hide the metadata, but it has to be there somewhere for SAML to function (though it may not be accessible on the SAML standard metadata format).

Assertions

Every SAML authentication exchange ends with the IdP sending a response containing an assertion to the SP or with an error. This assertion basically says, “You trust me, and I’m telling you who this is,” along with other attributes such as an email address, session information, full name, etc. These are usually fully configurable on the IdP. While nomenclature varies widely, including an attribute in the assertion is generally referred to as “releasing” it to the SP.

Certificates

Like Kerberos, SAML is designed to operate over an untrusted communication medium. As a result, the metadata contains information about how to ensure the assertion is not manipulated en route. This can be done on two levels: signing and message encryption. Most systems just utilize signing, since encryption doesn’t add much benefit unless additional sensitive information is being transmitted as part of the assertion. Signing only ensures the message wasn't modified en route between the two parties.

Unlike HTTPS, SAML does not require publicly signed certificates. The main reason it doesn’t need them is that the trust relationship is set up directly. The SP is told to trust the IdP because it is using a specific certificate. There is no need for a third party to verify the identity of the IdP, since this third-party verification is the entire point of publicly signed certificates.

The system clock

Yes, the humble clock that tells you what time it is. SAML is extremely dependent on both the SP and IdP having the same time (as is Kerberos). Generally, it is within five minutes, but this is configurable and can be reduced for an increased level of security. While it is clock time, the times are all expressed as UTC time, so the time zone of the systems should be irrelevant.

Ultimately, the clock protects against replay attacks, since modifying the timestamp would cause the signature to be invalid. There are other mechanisms that protect against replay attacks, but using the clock is the simplest.

SAML data flow

There are two modes in which SAML generally operates: SP-initiated and IdP-initiated. Not every system supports both both modes, but many do.

Communication Method

From here on out, we’re dealing only with web SSO based on SAML. If you’re truly interested in the other ways SAML can be used, there is a huge body of documentation out there, starting with the SAML specifications proper.

Communication between the IdP and the SP is entirely accomplished through the client web browser utilizing HTTP Post requests and JavaScript. The message passed is a base64 encoded XML document, with or without encryption, depending on the configuration. Think of the web browser as a relay passing messages back and forth between the SP and IdP. No direct communication between the SP and IdP is required, so an internal-only IdP can assert identities to a cloud service and vice versa. So, when we say that the SP sends something to the IdP, what we really mean is the SP tells the client web browser to post something to a specific URL. It is important to understand how SAML is utilized with cloud services.

SP-initiated SAML

In SP-initiated SAML, the client starts by accessing the login page of the SP. The SP usually presents a “login via SAML” button and, when clicked, the SP sends a request to the IdP to authenticate the user. In essence, this basically says, “Hi, I’m x app and I have a user who needs to be authenticated.” This is called an AuthnRequest.

One of two things need to happen at the IdP in response (assuming there isn’t an error):

  1. If the IdP has an active session with the client, it returns a response to the SP that includes an assertion of who the user is. This allows for the “SSO Experience.” The IdP tracks sessions, just like any other web app. Hungry yet? Want a cookie? So does your IdP.
  2. If the IdP does not have an active session with the client, it presents the login page, authenticates the client, then responds to the SP with an assertion.

The SP takes the assertion from the IdP and logs the user in to the app. The SP may do additional authorization checking, but you’ll notice the SP never got the username or password—just an assertion from the IdP that the user was who they said they were.

From this point on, the SP is responsible for maintaining the session and the IdP is out of the picture unless the SP needs to re-authenticate the user.

The message sequence is as follows (only relevant bits for general SSO are mentioned):

1. AuthnRequest sent from the SP to the IdP

  • Includes destination URL that the specific client will be directed to upon successful login
  • May include a request for a specific format of the NameID field in the IdP Response. This allows the SP to ask for UID vs. email vs. a short-lived ID, etc.
  • May or may not be signed or encrypted by the SP. If operating over HTTPS, encryption is generally not necessary.

2. Response sent from the SP to the IdP

  • Contains one or more assertions
  • Is signed, and may or may not be encrypted
    • Different elements may be included in the signature based on policies and the AuthnRequest
  • Contains an assertion
    • May (and in many cases, must) contain a NameID representing the user being logged in.
    • May contain a list of attributes

IdP-initiated SAML

In IdP-initiated SAML, the client starts by accessing the IdP and authenticating. With Okta, for example, you’d go to yourdomain.okta.com and log in. Clicking on one of the tiles initiates IdP-initiated SAML to an SP. Essentially, IdP-initiated SAML is the second half of SP-initiated SAML—the IdP already knows which URL to post the response to at the SP and knows how to deliver it. Unlike SP-initiated SAML, where the AuthnRequest can include specific requests and a redirect URL, IdP-initiated SAML always goes to the same URL at the SP. The practical implication is that if a session times out at the SP even if their session hasn’t timed out at the IdP, the user starts over at the default page at the SP.

Details and gotchas

Certificates/trust relationship

In order for SAML to function, the SP and IdP must trust each other. This trust is primarily given by the SP to the IdP, but it can be configured to require mutual trust in SP-initiated SAML flows.

Metadata file vs. metadata URL vs. GUI configuration

The “standard” configuration method between IdP and SP is by exchanging metadata XML files either via administrator upload/input or via a URL. With the URL approach, the metadata can contain an expiration date, causing the other party to automatically refresh the configuration. However, many systems do not support this approach, which can lead to some frustrating breakages after a system has been online for some time. One reason to not support metadata via URL is that it does open an additional attack vector on the system.

One of the common pitfalls with exchanging metadata XML files is certificate expiration. Should a certificate used in the SAML flow expire, everything must be reconfigured to include the new certificate among all parties. One advantage of the metadata URL approach is that it automates this process.

While metadata exchange is the standard mechanism to exchange config information between SP and IdP, many systems (such as Okta, G Suite, AzureAD, and ADFS) do not utilize it. With these major players in the space not fully utilizing the metadata config approach, it becomes necessary to translate between their (sometimes) proprietary terms and the underlying metadata equivalent.

Some systems only require configuration parameters instead of providing a metadata file, while other systems require a metadata file. OneLogin provides a handy tool that allows you to build metadata files. However, be careful with this tool, since you may consider your metadata sensitive. Additionally, the resulting metadata file from this tool contains additional information not configurable via the interface, which could cause problems (such as an expiration date). We recommend using the tool with dummy data, then editing the resulting metadata file with your actual data and removing the expiration information before uploading it to your SP or IdP.

EntityID

The most important item in the metadata is the “entityID.” Both the SP and IdP use it to identify each other. This is the key the IdP uses to determine where to send IdP-initiated SAML responses, and in SP-initiated SAML, how the IdP determines which SP it’s dealing with. In the SAML messages, this is the Issuer field. It is included in the metadata of both the IdP and the SP, if the specific implementation utilizes metadata. Knowing how to read the metadata and extracting the information your SP or IdP is requesting via their respective configuration interfaces is critical to successfully establishing the trust relationship.

Certificates

The SP, and sometimes the IdP, must trust potentially multiple certificates from one another. Some systems use configuration-specific certificates, while others use system-wide certificates. Most use system-wide certificates and different certificates for signing and encryption. The certificate is present in the metadata as a base64 encoded x509 certificate, without the “Begin Certificate” and “End Certificate” lines.

User Matching/Identification

While the IdP is responsible for authenticating the user, it must be able to communicate the user it has identified to the SP, including any required attributes of that user. Attributes can include things like an email address, real name, group membership, etc. Realistically, you can use an IdP to submit full directory context information to an SP, providing great support and centralized control of users’ information. However, for any of that to work, the SP must support it and be expecting those attributes to come from the IdP. Normally, the SP is responsible for authorizing and maintaining most user attributes.

This all sounds great and very flexible, but it leads to a thorny problem: How does the SP identify which user the IdP just authenticated? Take, for example, John Smith. John is internally known as j.smith (and logs in to the IdP as j.smith), but the SP uses an email as its internal user ID, so it’s expecting john.smith@example.com as a username from the IdP. How do we handle this? Unfortunately, it’s extremely SP-specific, so it falls to the IdP to provide the data where the SP is expecting it. Fortunately, most IdP implementations provide a translation capability to provide data in the format the SP expects.

NameID vs. attributes

The SAML Assertion may contain a NameID field. The NameID may be in different formats (a transient-id, a persistent-id, a username, an email, etc.) and is generally configured by the SP metadata. It can also be used in the AuthnRequest in SP-initiated SAML. This NameID field is the SAML equivalent of a UserID. However, what if the SP needs more than just one field?

Let’s take the Rapid7 Insight Platform SSO implementation as an example. The Rapid7 Insight Platform SSO implementation requires three attributes from the IdP to authenticate a user: FirstName, LastName, and Email. It needs all three because the SSO also functions as user procurement (if the user doesn’t already exist in the Insight Platform tenant).

These three attributes are included in the assertion from the IdP to the Insight Platform during IdP-initiated SAML SSO. In this particular implementation, the format of the NameID is irrelevant, since the Email field is what the platform is going to use to provision the account and to identify the user being signed in. The IdP must be configured to provide the required information and provide it in attributes with appropriate names.

For another example, let’s look at the SAML SSO implementation in InsightVM. Unlike the Insight Platform, the InsightVM SAML implementation utilizes the NameID field to match up to the email field in a pre-created account in its internal database. If the NameID field is not configured on the IdP to be the user’s email address, the SSO will fail, as the corresponding account in InsightVM will not be found.

Troubleshooting

Now that we’ve covered the basics of SAML, we may need to do some troubleshooting. With the protocol background above, we have a framework in which to troubleshoot our particular implementations. Since SAML is passing messages back and forth via XML through our web browser, it’s possible to examine the conversations and determine where any disconnect is happening.

Tools

While SAML messages are passed via the browser, the built-in developer tools in both Chrome and Firefox do not contain functions to make debugging SAML easy. You can see the messages, but they’re still base64 encoded and buried in the network traffic being passed back and forth between the browser, the IdP, and the SP. Fortunately, there are free plugins for both browsers that automatically detect and decode SAML messages, which makes debugging them much easier.

On Chrome, there is a SAML Message Decoder available, and on Firefox, there is the SAML-tracer. Both of these tools automatically detect SAML messages and decode them, allowing us to observe the messages being passed.

Handling encryption

During troubleshooting, it may be necessary to disable message encryption so you can actually see the full XML being passed during the SAML exchange. Most implementations don’t encrypt the messages again, just sign them, so it’s relatively unlikely this will be required. Encrypted SAML messages are much harder to troubleshoot since you can’t analyze the values being exchanged between the SP and IdP directly in the browser plugins.

Basic troubleshooting workflow

  1. Verify that the Issuer in the SAML message matches the Issuer/EntityID field in the configuration. For example, if you see an Issuer on an IdP response message, make sure it matches the IdP EntityID/name/etc. configuration on the SP.
  2. Verify the destination of the IdP response. It should match the SSO URL for the SP. If doing SP-initiated SAML, verify that the login URL for the IdP is correct.
  3. Verify the IssueInstant in the SAML message contains the right time. SAML Responses/Assertions are only valid until a certain time, and if the clocks are off, you’ll see a SAML message with an unexpected time. If the time is right, check the clock on your SP.
  4. Verify the format definition and the value of the NameID field. The value is readily available from the SAML response—ensure that it matches what the SP is expecting. If it is expecting a username, ensure that the NameID is, in fact, a username. Ditto for email address. Some SPs require that the NameID format in the response also matches what they’re expecting. The NameID format is generally one of the following:
    • urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
    • urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    • urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
    • urn:oasis:names:tc:SAML:2.0:nameid-format:transient
  5. Verify with the documentation of the SP that the attributes being returned in the SAML Assertion from the IdP have the proper attribute names (including case) and contain the expected values. Depending on your IdP, you may need to provide a custom mapping or establish a custom attribute on the user to achieve the proper attribute names.

Conclusion

Now that we’ve done a deep dive into SAML, I hope you have a stronger understanding of why SAML is important to implement and how to make it work in your environment. We encourage any fellow divers to further explore web-based SSO offerings. After all, SAML is not the only game in town. OpenID Connect/OAuth 2.0 offers many of the same benefits as SAML, and deciding between them is really just a matter of preference on behalf of the SPs of the world. Because of this, the big IdP services support both, thus allowing an organization to implement web-based SSO with almost all enterprise services available today, regardless of which system a specific SP has chosen to implement. Ensuring any IdP you choose to implement supports both will ensure you can spread the benefits of SSO throughout your organization and, ultimately, SAML ALL THE THINGS!