Welcome back to B2B Auth School. Our mission is to help B2B companies’ uplevel their understanding and implementation of user authentication technologies. Our first series of posts is dedicated to single sign on (SSO). This article is lesson six in that series.
Lesson one | Introducing B2B Auth School
Lesson two | Organization tenancy: the foundation of SSO and B2B data models
Lesson three | What is single sign on?
Lesson four | SSO protocols: SAML vs OIDC
Lesson five | What is OpenID Connect (OIDC)?
Lesson six | What is Security Assertion Markup Language (SAML) and how does it work?
Lesson seven | Choosing a B2B auth provider
In the previous lesson, we took a close look at OpenID Connect or OIDC – one of the two most popular protocols for handling single sign on (SSO). We looked at the origin of OIDC, its close relation to OAuth, and how that authorization protocol was built upon to create what is now quickly becoming a preferred standard for identity claims for federated, enterprise SSO.
Today we’re going to look at the other most popular SSO protocol, Secure Assertion Markup Language, or SAML protocol. We’ll look at:
It’s quite common for employees within large enterprise organizations to use a shedload of internal and external systems for work.
In a company that doesn’t leverage SAML or Single-Sign-On (SSO), employees would typically have to manage unique login credentials for each of these systems they need to access. While it’s obvious how much of a poor user experience this is, it also poses significant security risks that can have costly consequences for employees and the organization.
This is where SAML (Security Assertion Markup Language) comes into play.
Within organizations that leverage SAML, both intranet systems and SaaS applications don’t need to manage employee identity credentials directly. Instead, an identity provider (IdP) can assume this responsibility.
The IdP maintains up-to-date profiles and attributes for every user or employee and is responsible for exchanging these profiles with the applications employees need to authenticate into at any given time.
This approach eliminates the need for employees to manage multiple sets of credentials and redundant login processes across several work applications. It minimizes the burden of password memorization and mitigates the security risks associated with employees reusing the same password across multiple apps, or setting up weak and pattern-based passwords that can be easily compromised.
SAML is a federated identity standard that allows identity providers (IdPs) to exchange authentication and authorization details about a user with applications that require this information to grant or deny access to their systems.
It’s also referred to as an XML-based protocol because it uses the Extensible Markup Language (XML) to facilitate this communication between IdPs and SaaS applications (also known as Service Providers in SAML terminology).
Here’s how this communication works: Before an end-user can access a SaaS application via SAML, the service provider (SaaS application) must send an authentication request to the IdP, and the IdP must issue a valid SAML assertion to the application in the form of a digitally signed XML response.
This assertion contains essential information about the user, such as their identity and access privileges, represented as attributes, alongside conditions that specify the validity period and constraints of the assertion.
In this article, you’ll learn about the SAML protocol according to the latest version of the OASIS SAML technical overview document. We’ll explore the key roles and components of the SAML 2.0 specification, and demonstrate how IdP-initiated and SP-initiated SAML SSO flows work. We’ll also discuss the top alternatives to the SAML protocol and show you when to choose one over the other.
There are two main versions of the SAML standard—the SAML 2.0 version which is now widely implemented in B2B and B2E use cases, and the SAML 1.1 version which is largely deprecated. SAML 1.1 was adopted in 2003 as an improvement to SAML 1.0, which was introduced in 2002. But in 2005, SAML 2.0 was adopted as the latest OASIS standard, essentially replacing SAML 1.1.
SAML 1.1 and SAML 2.0 were both designed to achieve federated identity and single sign-on (SSO), allowing users to access multiple systems with a single set of credentials. However, SAML 1.1 had significant limitations in its implementation, causing SAML 2.0 to introduce some of the following key improvements:
The rest of this article will cover the other protocol improvements introduced with SAML 2.0.
There are five key elements that collectively function together to make the SAML protocol work. These include SAML Metadata, SAML Protocols, SAML Bindings, SAML Assertions, and SAML Profiles
Other profiles include the Single Logout Profile, which describes how users can be logged out from multiple applications simultaneously, and other less popular profiles. These profiles provide detailed guidelines for deploying SAML in different contexts, ensuring interoperability and consistency across implementations.
SAML and SSO are often used interchangeably or even seen as alternatives. While there’s a mutual relationship between these two concepts, there’s also a stark difference between them.
Single Sign-On (SSO) is a broad authentication concept that enables users to access multiple applications using a single set of credentials that must have been provisioned on a separate application that can vouch for their identity. Once authenticated in one application, users can seamlessly access other connected applications without having to re-enter any credentials.
On the other hand, SAML is one of the several open protocols that can be used to implement an SSO experience or functionality. As we’ve seen thus far, it defines a standardized way for identity providers (IdPs) to pass authentication and authorization data to service providers (SPs)—the application a user attempts to access.
In essence, SSO is the “what”—the desired functionality—while open protocols like SAML, OIDC (OpenID Connect), Kerberos, and OAuth 2.0 are the “how”—the methods used to implement this functionality. As such, the discussion shouldn’t be “SAML versus SSO” or “OIDC versus SSO,” but rather “SAML + SSO” or “OIDC + SSO.”
SAML SSO specifically involves transferring a user’s identity profile from an IdP to an SP using XML-based assertions. These assertions confirm the user's authentication status and are signed by the IdP to ensure their validity. In this way, users can access multiple applications that support SAML SSO by authenticating their IdP-provisioned credentials with the respective IdP, eliminating the need for separate credentials for each application.
Like OIDC, SAML authentication also works through a series of redirects and information that is conveyed along with those redirects. To start, let’s take a look at the main components.
The SAML SSO authentication flow is a trust validation process that involves the exchange of identifiers, metadata files, security tokens, relay state, session indexes, and other relevant attributes between the key roles within a SAML SSO setup.
The key roles within a typical SAML SSO authentication flow include:
The principal, or end user, is the human who initiates the authentication process in order to access a protected resource or application. This is typically an employee, customer, or partner of an organization who owns a single set of credentials they use to log into the company’s identity provider. The principal is central to the SAML SSO process, as the entire flow is designed to facilitate their access to several applications without repeatedly entering unique credentials on each one.
The browser agent acts as the intermediary between the principal, the identity provider, and the service provider. It’s usually the web browser or a similar client application that the principal uses to interact with the web.
When a principal tries to access a protected resource, the browser agent initiates the SAML SSO process by redirecting the authentication request to the IdP. After successful authentication, the browser agent also handles the redirection of the SAML assertion from the IdP back to the SP. The browser agent is also responsible for storing and transmitting cookies that maintain the user's session state.
The IdP is a trusted entity that authenticates the principal’s identity. It maintains the principal’s credentials and profile information and verifies their identity whenever they attempt to access a service provider. Upon successful authentication, the IdP generates a SAML assertion which contains information about the user’s identity, authentication status, and other relevant attributes. This assertion is digitally signed and sent to the SP via the browser agent.
A service provider is the application or system that a principal is trying to access. The SP trusts the IdP to authenticate the principal and issue an assertion that confirms their identity and associated attributes. Once it receives a SAML assertion from the IdP, the SP validates the assertion's integrity and authenticity and uses the information within it to make access control decisions. If the assertion is valid, the SP will automatically grant the principal/user access to the requested resource or service, without having to manage the user authentication process by itself.
An auth provider like Stytch isn't a necessary component within a custom in-house SAML SSO setup. However, organizations can choose to build their SAML SSO infrastructure using third-party auth providers, in which case Stytch could become part of your SAML authentication flow.
Auth providers like Stytch don't function as standalone identity providers such as Okta or Microsoft Entra ID. Instead, they provide the APIs and SDKs that make it easier for developers to implement SAML SSO in their applications without directly handling the complexities of the SAML protocol.
Stytch only acts as an intermediary that standardizes the authentication process across multiple identity providers and can integrate with any organization’s IdP. The IdP remains solely responsible for authenticating users and issuing SAML assertions. Stytch's role is to facilitate the authentication process between the IdP and SP, forwarding XML requests and assertions between them.
Let’s assume we have an employee who needs to access a SaaS application to complete a task, maybe Figma in the case of a designer or GitHub in the case of an engineer. If these applications support SAML SSO, our hypothetical designer or engineer could access Figma or GitHub in two ways—via the service provider-initiated (SP-initiated) SAML SSO flow or the identity provider-initiated (IdP-initiated) SAML SSO flow.
In the SP-initiated flow, the user must attempt to access the SP directly (e.g., Figma or GitHub's login page). As such, the SP has to redirect the user to their IdP with a SAML authentication request (AuthnRequest). Once the user authenticates their IdP-provisioned credentials, the IdP would have to generate a SAML assertion and return a signed response to the SP. The SP then validates this assertion and grants or denies access to the user.
On the other hand, the IdP-initiated flow begins at the IdP portal and doesn’t require an initial SAML AuthnRequest from the SP. Firstly, the user must log into their IdP and select an SP (e.g., Figma or GitHub) from a list of SAML-enabled applications. Upon selecting the application, the IdP has to generate a SAML assertion and send it to the chosen SP. The SP then validates the assertion and grants or denies access.
In both flows, the common steps include the IdP authenticating the user, generating a SAML assertion, and the SP validating this assertion to grant access.
To fully understand the SAML authentication process, we need to study the XML anatomy of SAML requests, responses and assertions.
As we’ve seen so far, SAML messages come in two forms—SAML requests and SAML responses.
The main difference between them is the direction in which they are sent. A SAML request is sent from the service provider to the identity provider in order to authenticate a user’s identity, while the identity provider sends a SAML response to the service provider to convey authentication status, assertions and other requested information about the user.
SAML requests are initiated by the SP to request authentication from the IdP on behalf of a user. These requests typically contain information such as the request ID, the SP's entity ID, and the ACS URL where the IdP is expected to send the response.
We won’t be going deep into XML semantics or schema, but if you want more specific information on SAML data schema or namespaces (mentioned below) check out page 11 in the SAML specs.
Here’s an example of a SAML request in XML:
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="this-is-a-request-id"
Version="2.0"
IssueInstant="2022-12-29T11:39:34Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP POST"
Destination="https://b2b-customer.identityprovider.com/app/123456/sso/saml">
AssertionConsumerServiceURL="https://serviceprovider.com/sso-callback/callback-id-123">
<saml:Issuer
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
https://identityprovider.com/123456
</saml:Issuer>
<samlp:NameIDPolicy
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
AllowCreate="true" />
<Signature> ... </Signature>
</samlp:AuthnRequest>
From top to bottom, we can deconstruct this XML request into its most important parts and summarize their meaning:
In summary, this SAML request is bound to an HTTP POST and is being sent to the specified destination and entity ID within the request. It asserts that it needs an email address in the response when returned to the callback URL. Congrats, you’re now successfully reading SAML.
SAML responses are a much longer and nastier XML document, because they contain more information. They contain one or more assertions, which include details about the user's authentication status, attributes, and any other relevant information. These responses are created and signed by the identity provider before they’re sent to the requesting service provider for validation. They’re the most important artifact in a SAML authentication flow, since they carry all the assertions necessary for SSO to work.
To examine the structure of SAML responses, we’ll have to break the full SAML response into three parts.
SAML response – part one:
<saml2p:Response
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
Destination="https://serviceprovider.com/sso-callback/callback-id-123"
ID="id74288802592086131551222311"
InResponseTo="this-is-a-request-id"
IssueInstant="2022-12-29T22:15:54.006Z"
Version="2.0">
<saml2:Issuer
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
http://www.identityprovider.com/123456
</saml2:Issuer>
<ds:Signature> ... </ds:Signature>
...
</saml2p:Response>
At this point, part one should look familiar. Like the SAML request, the SAML response has a top level (root) element called the Response with attributes like xmlns and Destination, but with updated values. For example, the Destination attribute now specifies the service provider’s callback url that will parse and validate the SAML response.
SAML response – part two:
<saml2p:Response>
...
<saml2:Assertion
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
ID="id7428880259355886991749372"
IssueInstant="2022-12-29T22:15:54.006Z"
Version="2.0">
<ds:Signature> ... </ds:Signature>
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">
your_user@email.com
</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData
InResponseTo="this-is-a-request-id"
NotOnOrAfter="2022-12-29T22:20:54.006Z"
Recipient="http://serviceprovider.com/callback"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
NotBefore="2022-12-29T22:10:54.006Z"
NotOnOrAfter="2022-12-29T22:20:54.006Z">
<saml2:AudienceRestriction>
<saml2:Audience>audience_entity_id</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
AuthnInstant="2022-12-29T22:04:28.918Z"
SessionIndex="this-is-a-request-id">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
...
</saml2:Assertion>
</saml2p:Response>
Part two of the SAML response is where all the relevant assertions start to come in. These assertions give context about the user and how they authenticated with the identity provider. The Assertion element wraps all the data statements, which include:
SAML response – part three:
<saml2p:Response>
...
<saml2:Assertion>
...
<saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:Attribute
Name="name"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string">
Ada Lovelace
</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute
Name="phonenumber"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string">
+1 (123) 456-789
</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute
Name="groups"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
Group One
</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
Group Two
</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>
And finally, part three contains all the assertions about the user’s identity and profile. These user assertions are called attributes. Common attributes about a user include but are not limited to name, phone, email, location, etc. In our example, you’ll see an Attribute element for:
These attributes provide a robust profile of a user’s identity. And that’s because attributes are customizable, in the sense that assertions can include about as much information and metadata an IT admin cares to stuff in there. However, it's important to note that each identity provider has its own unique and generally configurable set of attributes for a user, which means the service provider will need to understand how to interpret them correctly.
Adding all three parts together, the SAML response gives a full picture of the authentication flow and the user’s identity. But with multiple assertions and custom attributes, the length and format of the XML starts to multiply in complexity very quickly. However, the service provider must be able to parse and validate all the different variations of SAML syntax and assertions.
If you’re a B2B company looking to move up-market or already serving enterprise clients that have custom security needs, you can implement the SAML protocol in weeks or even days using Stytch.
Many B2B companies either attempt to build SAML internally or choose auth providers that lack the flexibility needed as they scale. Unfortunately, both approaches end up draining engineering resources and then require even more time to rip and replace.
From our experience, and that of our customers, we wouldn’t advise any engineering team to attempt building SAML in-house. In addition to wasted resources, it’s easy to leave vulnerabilities that could make your infrastructure open to attackers.
However, with Stytch, you can easily and securely configure SAML for your enterprise customers regardless of the identity provider they use within their organization. Using Stytch, you can connect to any SAML-enabled service provider because we can forward AuthnRequests to whichever IdP, and also forward SAML responses back. It’s that easy and straightforward.
Ready to implement SAML SSO with Stytch? Check out our Docs and start coding.
If you have any questions, please reach out to us at support@stytch.com or schedule a chat with a member of our Solutions Engineering team.