How SAML 2.0 Authentication Works

Introduction

With Teleport, we offer integrations for SSO with a number of services including Okta, Auth0, Active Directory, and more. But all of these services are based on one of two protocols: SAML or OAuth/OpenID. Of the two, SAML 2.0, released in 2005, remains the 800 pound gorilla in Enterprise SSO space and we wanted to give a quick introduction on how it works.

At its core, Security Assertion Markup Language (SAML) 2.0 is a means to exchange authorization and authentication information between services. SAML is frequently used to implement internal corporate single sign-on (SSO) solutions where the user logs into a service that acts as the single source of identity which then grants access to a subset of other internal services.

The advantage of adopting SAML/SSO from a security perspective are clear:

This particular post will be focused on providing an overview of the how and why of SSO and SAML.

Terminology

Unfortunately before going any further we have to define some SAML-specific terminology, of which a fair amount exists.

The principal is the user trying to authenticate. You can think of this as the actual human behind the screen, for the remainder of this post, we’ll assume it’s John Smith.

An Identity Provider, frequently abbreviated as IdP, is the service that serves as the source of identity information and authentication decision. Identity providers authenticate principals and return identity information to service providers (see below). A few examples of common identity providers: Auth0, ADFS, and Okta.

Service providers, frequently abbreviated as SP, are the services that are requesting authentication and identity information about the principal. Service providers take authentication responses received from identity providers and use that information to create and configure sessions.

SAML supports two different types of flows: those initiated by the service provider and those initiated by the identity provider. In this post, we’ll cover the common SP-initiated flow. In SP-initiated flows, you start out at the service provider, are redirected to the identity provider to authenticate, and are then redirected back to the service provider.

Bindings are the format in which data is transferred between service providers and identity providers. The two most popular are HTTP Redirect Binding and HTTP POST Binding. HTTP Redirect Bindings transfer data using HTTP redirects and query parameters; this type of binding is typically used in authentication requests. HTTP POST Binding transfer data using HTTP POST forms, this type of binding is typically used in authentication responses.

Assertions are statements made by the identity provider about the principal. For example, the principal’s email address and/or groups/roles the principal may be associated with. Assertions are used by the service provider to create and configure sessions for a principal.

SAML Login

SAML login

Figure 1: Overview of SAML login with Teleport.

Configuration

Identity providers all have their own unique methods of configuration. However, the following minimal set of configuration is needed for the identity provider to work with a service provider.

Service provider configuration is typically simpler, and can often by automatically configured by parsing metadata provided by the identity provider. Simplified identity provider metadata XML is shown in Figure (2) below. The most important tags are SingleSignOnService and KeyDescriptor. The SingleSignOnService tags define the binding and endpoints to send authentication requests to, and the KeyDescriptor tag contains the public key of the identity provider which will be used to validate the authentication response.

<md:EntityDescriptor>
  <md:IDPSSODescriptor>
    <md:KeyDescriptor use="signing">
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509Certificate>
            MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
            MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
            NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
            AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
            AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
            CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
            fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
            AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
            FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
            BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
            oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
            kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </md:KeyDescriptor>
    <md:NameIDFormat>
       urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    </md:NameIDFormat>
    <md:SingleSignOnService
      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      Location="https://idp.example.com/saml"/>
    <md:SingleSignOnService 
      Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
      Location="https://idp.example.com/saml"/>
  </md:IDPSSODescriptor>
</md:EntityDescriptor>

Figure 2: Simplified metadata from an identity provider.

Authentication Request

To begin the login process, the principal typically will navigate to the service providers login page, and then click on a button that reads something like, “Login via SSO.”

At this point the service provider will create an AuthnRequest XML document, serialize it (base64, compress, and URL encode), add it as a query parameter to the URL, and redirect the principal’s browser to the identity provider’s login page. As the name of the request implies, the service provider is requesting the identity provider to perform authentication on its behalf. It should go without saying that this (and all other requests and responses) should occur over HTTPS.

The AuthnRequest is often sent using HTTP Redirect Binding, and ends up looking something like the following:

https://idp.example.com/saml?SAMLRequest=nFdpk6JK0%2F0rHc7...

Where the SAMLRequest parameter is the encoded AuthnRequest, a simplified AuthnRequest follows.

<samlp:AuthnRequest
AssertionConsumerServiceURL="https://sp.example.com/saml/acs"
Destination="https://idp.example.com/saml"
ID="bcf0b634-67b4-4dc9-a436-4e5cfcfb80e2"
IssueInstant="2019-04-17T18:15:16Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0">
  <saml:Issuer>
  https://sp.example.com/saml/acs
  </saml:Issuer>
  <ds:Signature>
    <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="#bcf0b634-67b4-4dc9-a436-4e5cfcfb80e2">
        <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/2001/04/xmlenc#sha256" />
        <ds:DigestValue>
        XBCrZlFG5PxsHkeo5zNeRtDnB9rZEbo4R0HwFbl6O3c=
        </ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>
    PLslJMUXoW99FDpFdlUdKojYJbJWhWaJ8URQOOGAqXQ/QAF2mLsdJOOu834H9T7USVkeWn7e1NuK
    9pV6C0CEo/INaT/2knWH/OlRl2jH0e+NR9bLcGY49MBAqaqCd/FbHm/bvPEerM2SrLkYA9dmN5vE
    6NVm5cvdMue9KZRnRZ4j5BAstC03Fd9/5OGetgcDiIlNMTDjhEuSgijVR0+jkSgPu/mZLfQ3IT+9
    tcHvC9VUuigVRXGEqOHsd2yX4Rhl9f6u1Y0BAg82RerHg6VEzxM9ZDvIyKIq/Ne8Hz0COlVWrJ/a
    qoi9RzROfPFOsEW8ohLUeZ74QS93jYztfY4BzA==
    </ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>
        MIIDKjCCAhKgAwIBAgIQUBVD9B5t9U5IvGFV2F/igDANBgkqhkiG9w0BAQsFADBAMRUwEwYDVQQK
        EwxUZWxlcG9ydCBPU1MxJzAlBgNVBAMTHnRlbGVwb3J0LmxvY2FsaG9zdC5sb2NhbGRvbWFpbjAe
        Fw0xNzA4MTYxOTU0NTFaFw0yNzA4MTQxOTU0NTFaMEAxFTATBgNVBAoTDFRlbGVwb3J0IE9TUzEn
        MCUGA1UEAxMedGVsZXBvcnQubG9jYWxob3N0LmxvY2FsZG9tYWluMIIBIjANBgkqhkiG9w0BAQEF
        AAOCAQ8AMIIBCgKCAQEAopoQnx7RELetBxUlkRZnSHLRYakETx6OiwCqlArC89tXsTmbv71AsQJJ
        j0Xys7py5gfcKF2onjSj3FMX/ApxjdQIiq7+60g3WIRsaTSIGaHU/Gq/GQXPIfGxvDEp+mnytD7Q
        C39VyeUHIDicXv1IluGvolxtxjU8Fi/tGpCEuhREhfcOiXOaRMA8ABPHj6qLZOaq80yIxuUqv2jP
        aRw2jvAcCLUtOF4W5gs+3ms9d/qZRjIEPkrzPiEHRAVvcUb4Lutwx1YJcPUPviIVdcH7JiWj2eEU
        9fObjrxvLJ2ZMET4bz/thH3okOvkfvE0Xt0L6G9Gv08wqsmwWP0BNJYTwQIDAQABoyAwHjAOBgNV
        HQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEASguYy7pt3DoJ24rs
        MDTBa9+ZsVfgHHmCbwhXgyt1siXdA8USluYwOGnECo+yuOdfFK2545UPpNp5G5pGGxSf0LP1Usud
        ANQ97R6vF7XIYJAmVgHITMpjuVgGlJi1+Ro2NzoX1EF8X2GowJr6hehERCSL16PVXAo/b41ypMad
        3yTMKW6YNWEoBftZfhSjb9ZVpbGomgE20UMtp0d601MZy20M8zJBEH4yXhxzJ1/3nJpfW4c3VOK6
        QDDJpFFPl4GZwF31qcpIPSpHuokbskkhnSgiPjdc8k73q3bIyg7RonTvf8kfmD5TU+K9pOIKvF48
        JVyH0UBaXnojNYyltHgXnA==
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
</samlp:AuthnRequest>

Figure 3: Simplified authentication request sent by the service provider to the identity provider.

A few things to note about the AuthnRequest.

The service provider generates a large secure random number and inserts it into the ID field in the AuthnRequest tag. This value is also stored locally (typically in a database) and is used to pair requests with responses from an identity provider and to prevent a malicious third party from sending an unsolicited response to a request (it would not know the ID).

To prevent the re-use of expired AuthnRequests, the identity provider needs to store and track which ID values have been used thus far. Without some kind of time bound, this would lead to the identity provider needing an ever increasing amount of storage. The IssueInstant is used to generate that validity window for the request.

The service provider should sign the AuthnRequest. The SAML signing scheme includes the signature, key used to sign the request, and information on how to calculate the signature all under the Signature tag. The identity provider should not only validate the included key was used to sign the request, but also that the key is the same as the one uploaded during configuration (see previous section). If the key does not match, is missing, or if the signature values do not match, the identity provider knows the request is not legitimate and to reject it. XML digital signatures, which is what SAML uses to sign requests, are a large and complex topic in itself, Signing an XML document using XMLDSIG is a good place to start to learn more.

Authentication Response

Returning back to the authentication flow, at this point the principal is sitting at the login page of the identity provider. If the principal enters their correct login credentials, the identity provider will perform a 302 Redirect to the ACS URL of the service provider with body containing the authentication response. In the example we have been tracking, the ACS URL would look like the following:

https://sp.example.com/saml/acs

A simplified SAMLResponse would look like the following:

<saml2p:Response
Destination="https://sp.example.com/saml/acs"
ID="id35287812421219341967493380"
InResponseTo="10b5507d-a8a5-41c2-b34a-86de64df7cae"
IssueInstant="2019-04-18T18:51:46.729Z">
  <ds:Signature>
    <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="#id35287812421219341967493380">
        <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/2001/04/xmlenc#sha256" />
        <ds:DigestValue>
        tyLUm4r2isgN+L6sRcqDSEa1Zb7WQbQJG6PpLcf3Mrc=
        </ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>
    XjqbZty/QkqTnMV8YsS2XJ3qgVLPGNC67o/WmzkzoAyl3SBOCGllV4UdijkTjhgykQP7MVXyCql0
    eRtIMJ++rbi3OxCSc0LN67znuTS7cAfcOQzYBtYX2R9w3GlEAO0kZusWYlP3cu/ObmQZUQ7CSgr4
    DRXsVWRhSmmpxHl6klC6c10eWiIlK7Ccpvvvb2hlwl8anyuO/CcKH0n/Rb9vHWtsAlqKXZ8G4X6M
    77AfRFC7yDWk+8B784109phQxcxoDYjuQNO5IkiRE6J2LnkmuaPoKVyTtpP2JYLiYMSBu8laDsnZ
    I/ewOtBwr16j9oOJpgHPQufQJfvcg+rPEwkptg==
    </ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>
        MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
        MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
        NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
        AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
        AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
        CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
        fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
        AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
        FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
        BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
        oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
        kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
  <saml2p:Status>
    <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
  </saml2p:Status>
  <saml2:Assertion
  ID="id35287812421980111258419174"
  IssueInstant="2019-04-18T18:51:46.729Z">
    <ds:Signature>
      <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="#id35287812421980111258419174">
          <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/2001/04/xmlenc#sha256" />
          <ds:DigestValue>
          VKPsgTPABNq1SvInCMXd04LZCvRYMnJzEeT5oIs70hw=
          </ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>     
      gsUzQuivXX378HkYNI+plBkp1BvPUNmJD+kh825nHwIBNd019IxffVmOfRAQAkZhT6rqxWhO5/Yc
      JGR5J0qjJVmrRrJ/ipT4VfuJsbn346nEFSMU15D0h3UHrvl651C+NStyXsi8Q8502Qe0ChHOtEXM
      rw9HWPwYtJX0rlpNEzLUnEQPvJ4pd3bz9SIl/YXMNTxE7NCDOxPXKtA4namkkweilxTCynM6A1kn
      6gEWaXhLMwLLAV6kOtivdVksBPzR9BeZ7RPpXeqt0qN62L4NaHq3OsdjgtQr9sllssD1fEek1eU4
      giCzPgb1+LjvD9dpFH5pcLt9YlwHyYgEBBLOQg==
      </ds:SignatureValue>
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509Certificate>
          MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
          MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
          NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
          AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
          AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
          CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
          fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
          AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
          FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
          BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
          oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
          kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </ds:Signature>
    <saml2:Subject>
      <saml2:NameID>
      [email protected]
      </saml2:NameID>
      <saml2:SubjectConfirmation>
        <saml2:SubjectConfirmationData 
        InResponseTo="10b5507d-a8a5-41c2-b34a-86de64df7cae"
        NotOnOrAfter="2019-04-18T18:56:46.730Z"
        Recipient="https://sp.example.com/saml/acs" />
      </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions
    NotBefore="2019-04-18T18:46:46.730Z"
    NotOnOrAfter="2019-04-18T18:56:46.730Z"
    xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
    </saml2:Conditions>
    <saml2:AuthnStatement
    AuthnInstant="2019-04-18T18:51:46.729Z"
    SessionIndex="10b5507d-a8a5-41c2-b34a-86de64df7cae">
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
      <saml2:Attribute Name="logins">
        <saml2:AttributeValue>
        root
        </saml2:AttributeValue>
        <saml2:AttributeValue>
        jsmith
        </saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="groups">
        <saml2:AttributeValue>
        admins
        </saml2:AttributeValue>
        <saml2:AttributeValue>
        developers
        </saml2:AttributeValue>
      </saml2:Attribute>
    </saml2:AttributeStatement>
  </saml2:Assertion>
</saml2p:Response>

Figure 4: Simplified authentication response sent by the identity provider to the service provider.

When a service provider receives an authentication response, it should first check if the InResponseTo attribute references an ID of an AuthnRequest that the service provider actually sent. In addition, the IssueInstant attribute should be used to scope the validity window of the response. The reasoning for why these are important has already been explained in the previous section.

The ACS URL to which the authentication response is delivered performs no authentication of the client, this is why the Signature in the authentication response must be checked to ensure the client is the identity provider. For readers familiar with the concept of webhooks, this is conceptually very similar: information is exchanged out-of-band ahead of time (often an API key in the case of webhooks) which is then used to authenticate the client.

The response also contains four new interesting tags: Status, Subject, Conditions, and AttributeStatement:

As mentioned above, it’s important to keep in mind assertions about a principal are a snapshot in time of identifying information. Providing long lived assertions or sessions is, in general, a security risk. Keep assertions and sessions reasonably short lived and force re-authentication to ensure that any assertions that the identity provider made about the principal are still valid.

Conclusion

What a service provider does with the response is up to the discretion of the service provider. However, typically a successful response will create a session on an internal service providing a single source of identity and consistent authentication across internal services.

Hopefully that provides a good snapshot of how SAML works. If you’d like to learn more about how we integrate with various SSO services you can read more on our SSO for SSH documentation.

sso saml teleport

Want to stay informed?

Subscribe to our weekly newsletter for the latest articles, industry changes, and products updates.

Connect with Us

IoT Security, FedRAMP Support: New in Teleport 4.0 By Jon Silvers SSH Handshake Explained By Russell Jones Teleport Helps Auth0 Meet PCI and SSH Requirements By Jon Silvers

Start Using Teleport Today

Teleport gives you security best-practices out of the box for the privileged access management of your cloud-native infrastructure.

Demo Teleport Download Teleport