This post was originally published as “SAML 2.0 VS. JWT: UNDERSTANDING FEDERATED IDENTITY AND SAML” on the Levvel Blog.
This post continues our ongoing discussion regarding API security and will be the first in a series dedicated to the topics of SAML and JSON web tokens (JWTs). This series will build upon concepts already discussed in the Digital Signature series and the API Security vs. Web Application series.
The first part of this series discusses SAML 2.0 use cases and requirements. Although there are many SAML 2.0 use cases, we’ll focus on the use of SAML 2.0 bearer tokens for web application single sign-on and with SOAP Web Services and WS-Security, because these are a forerunner to the use of JWT with APIs.
This stuff has been around a while; I gave a presentation at IBM Impact in 2011 on the use of SAML with SOAP web services and an enterprise service bus (ESB). When I first saw the JWT, OAuth2, and OpenID Connect specs, I saw something similar to what I had already been working with. Similar, but simpler.
WHAT IS SAML?
SAML is a family of OASIS specifications created by the Security Services Technical Committee that describes an “XML-based framework for communicating user authentication, entitlement, and attribute information” to actors participating in a trust relationship. The Security Services Technical Committee has a motto published on their website:
Defining and maintaining a standard, XML-based framework for creating and exchanging security information between online partners.
That sums up nicely what SAML is all about. The SAML specification defines several actors that are present in every use case: Identity Provider (IdP), Relying Party (RP) or Service Provider (SP), and principal. The IdP authenticates principals and issues tokens (or assertions). The SP is an application or resource that is protected and requires authentication and authorization of any principal wishing to access it. The principal (typically a user, though maybe a system actor) is an entity that can be authenticated.
Authentication is the process of the principal proving its identity to the system. Authorization is the process by which a protected system (the SP, in this case) makes a decision of whether an authenticated principal is allowed to access the system. Sometimes, the authentication and authorization decisions are offloaded from the SP to an intermediary, such as an ESB or Security Gateway.
A SAML 2.0 token or assertion (the term the specification uses) is an XML document that contains (or can contain) information about:
- The authenticated principal (subject)
- Security attributes describing the user (SAML attributes)
- Information about the IdP (issuer)
- Information about the SP (conditions, audience restriction information)
- Valid time frame (starting date, expiration date, issuing date)
- Digital signature
- Subject confirmation method
- How the principal was authenticated
- Encryption information
The authenticated principal is generally referred to as a “subject” and is typically a simple username, a user’s distinguished name (DN), an email address, or a domain qualified username. This name typically references a user defined in the user repository (LDAP, Active Directory, etc.) that is part of the IdP. We’ll talk more about user repositories later.
The security attributes could include role information, LDAP attributes, highly context-specific attributes that are meaningful to the SP, or just about anything else. These security attributes are an example of claims in a claims-based identity system. SAML is an example of an implementation of a claims-based identity system. Claims-based identity provides a common framework for actors, applications, or systems to acquire identity information about users and the issuer (or authority) that issued those claims. In this system, a claim is a statement (think of it as a SAML attribute, the username, group information, or the like) that one subject — the issuer — makes about another subject, the principal. We’ll call this the abstraction and theory behind SAML 2.0 and JWT. We’ll come back to claims-based identity down the road.
The SAML 2.0 spec defines a concept called “Subject Confirmation Method.” The most common one is the bearer subject confirmation method. This allows SAML 2.0 assertions to act as bearer tokens. The subject confirmation method is the mechanism by which an entity provides evidence of the relationship between the subject named in the token and the SAML assertion’s claims. By definition, there are no additional steps needed to establish the relationship between the subject and the claims for bearer tokens. The relationship is implicit, per the spec. You might recall from our earlier discussion of bearer tokens that the really useful ones include a digital signature, which is interesting, since that breaks the notion that the relationship is implicit. But that’s how bearer tokens usually work in the real world. A bearer token with a digital signature is also far more secure than one that is not (but it does have its limitations).
The other two subject confirmation methods are sender vouches and holder-of-keys. I once supported a shop that used the IBM Integration Stack (including WebSphere DataPower) to integrate SAP and dozens of other Commercial Off The Shelf (COTS) products with Active Directory Federation Server v2.0 (ADFS) as the IdP. The SAP modules in play did not support bearer tokens; only the sender vouches and holder-of-key methods were supported. ADFS did not support sender vouches; DataPower supported all three subject confirmation methods. So, the SOAP Consumer obtained a SAML bearer token from ADFS, made a SOAP call to DataPower, which validated the token and swapped it out for a sender vouches SAML token that it generated, then sent the request with the sender vouches token to an SAP SP. I often use the term “security integration” to describe this type of integration work.
Below is an example of a SAML 2.0 token:
<?xml version="1.0" encoding="UTF-8"?> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_0" IssueInstant="2016-05-14T00:10:00.123Z" Version="2.0"> <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://idp.levvel.io/sso/saml2/token</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/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="#_1"> <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>M9CyzmcJfLg8JDO48590345f9sfdew0</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> [ omitted for brevity ... ] </ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> [omitted for brevity...] </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml:Subject xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">email@example.com</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:SubjectConfirmationData NotOnOrAfter="2016-05-14T00:15:00.123Z" Recipient="https://app1.levvel.io/login"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2016-05-14T00:10:00.123Z" NotOnOrAfter="2016-05-14T00:15:00.123Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:AudienceRestriction xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:Audience>https://app1.leevvel.io/login</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AttributeStatement> <saml:Attribute Name="givenName"> <saml:AttributeValue>John</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="surname"> <saml:AttributeValue>Doe</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="roles"> <saml:AttributeValue>admin</saml:AttributeValue> <saml:AttributeValue>advancedView</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> <saml:AuthnStatement AuthnInstant="2016-05-14T00:10:00.123Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:AuthnContext xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion>
Obviously, this is an XML document. It’s top-level element is called Assertion (hence the name SAML Assertion). I also refer to this as a SAML token on occasion, though this isn’t taken from the spec. Below are the sub-elements and their function, in order:
- Issuer: the URL of the IdP that issued the assertion.
- Signature: the Signature element has already been covered.
- Subject: contains a NameID element (the authenticated principal name) and a SubjectConfirmation element. The SubjectConfirmation element defines the subject confirmation method used by this token. For use cases described in this series, this will always be bearer of token.
- Conditions: describes the Audience information that provides the Relying Party and time period for which this token is valid.
- AttributeStatement: contains a list of attributes (usually referred to as SAML Attributes) that describe the user in more detail and are meaningful to the SP.
The SAML 2.0 spec addresses authentication and authorization concerns. From a practical standpoint, however, there is almost always additional information placed in the Assertion and additional processing steps needed for the Authorization step beyond what the spec defines in all but the most trivial of use cases. One such case is Web App SSO, where any authenticated user is allowed to access the web application. A very common example of additional information that needs to be passed as custom claims (SAML Attributes) in SAML 2.0 bearer tokens is role information, or a list of groups of which the principal is a member. Defining and processing the authorization policy that maps the SP’s resources to specific roles or other claims is a separate topic.
Numerous edge cases and optional features exist in the SAML 2.0 family of specs that I won’t get into here. For the most part, they aren’t important to our discussion. It is important, however, to remember that the SAML 2.0 spec is very flexible and has numerous optional pieces. Likewise, some pieces of the spec can be a bit vague and open to interpretation; the SAML 2.0 token with which you may be dealing could look almost exactly like the one above or quite different.
A BRIEF HISTORY OF SAML
I always try to give the history behind how things got to be the way they are because I find this helpful in understanding both the larger picture and how the individual pieces fit into it. The history of SAML2, WS-Security, and WS-Trust is filled with complexity and frustration; the writers of the JWT, OAuth2, and OpenID Connect specs were very familiar with these difficulties.
SAML builds on top of the XML, XSD, XML Signature, XML Encryption, HTTP, and SOAP specifications. The SAML 1.0 spec was published in November, 2002. The SAML 1.1 specification came shortly after that in September, 2003. Around this time, the Liberty Alliance was producing a body of work that extended SAML 1.0 and eventually formed the basis of SAML 2.0, which was published in March, 2005. SAML 1.0 is not commonly used at this point, though I have seen SAML 1.1 Assertion in use in a production environment within the past year. SAML 2.0 is much more commonplace and is the workhorse of Federation and SSO throughout most large enterprises. It is beginning to be supplanted by OAuth 2.0 and OpenID Connect, however.
SAML 1.1 and 2.0 are not a single spec, but rather a family of interrelated specs. I’m dumping the list straight from the Oasis website in this section; not terribly creative, but it prevents me from having to go look this stuff up constantly. I will reference this periodically throughout this series.
The approved specification set consists of:
- Assertions and Protocol (oasis-sstc-saml-core-1.1)
- Bindings and Profiles (oasis-sstc-saml-bindings-1.1)
- Conformance Program Specification (oasis-sstc-saml-conform-1.1)
- Glossary (oasis-sstc-saml-glossary-1.1)
The XML schema files for SAML 1.1 are:
- Assertion Schema (oasis-sstc-saml-schema-assertion-1.1.xsd)
- Protocol Schema (oasis-sstc-saml-schema-protocol-1.1.xsd)
Additional documents related to the version 1.1 specifications are:
- Errata (sstc-saml-errata-11-draft-16)
- Security and Privacy Considerations (oasis-sstc-saml-sec-consider-1.1)
- Version 1.1 Issues (sstc-saml-issues-1.1-draft-01)
- Differences from v1.0 (sstc-saml-diff-1.1-draft-01)
The original approved specification set (without errata markup) consists of:
- Assertions and Protocols (also known as “Core”)
- Assertion schema
- Protocols schema
- DCE attribute profile schema
- ECP profile schema
- X.500 attribute profile schema
- XACML attribute profile schema
- Metadata schema
- Authentication Context
- Conformance Requirements
- Security and Privacy Considerations
- Glossary (also available in HTML)
WHAT COMES NEXT
In the next post, we will begin looking at the various use cases for SAML 2.0 and examples of each. This part of the series is admittedly not the most exciting, but it does serve as an important first step toward our goal of making a detailed comparison between SAML 2.0 and JWT. It also serves as a useful introduction to those who are unfamiliar with the topic. Stay tuned; there is much more to come on the topic of SAML and JWT.