Overview of SAML 2.0 Single Sign On Authentication with Coding Example

Overview of SAML 2.0

Security Assertion Markup Language (SAML) version 2.0 is an XML-based protocol that uses security tokens containing assertions to pass information about a principal (usually an end user) between a SAML authority, named an Identity Provider, and a SAML consumer, named a Service Provider.

Note: See the bottom of this post for a useful SAML glossary of terms.

A typical scenario for implementation is:

  1. Your user is logged in to a company web site or a commonly used web site
  2. The user needs to access an external system that has an account for the user already configured. Ideally the user would be able to seamlessly access the external system with out having to login again.
  3. In this scenario, SAML integration can be implemented between the currently system and the external system.

SAML provides a standard for logging users into an application based on their session in another context. This single sign-on (SSO) login standard has significant advantages over logging in using a username/password:

  • No need to type in credentials
  • No need to remember and renew passwords on different systems
  • Helps to eliminate the use of weak passwords
  • If the user should no longer face access it can be turned off for all integrated systems

Most organizations already know the identity of users because they are logged in to their local domain. It makes sense to use this information to log users in to other applications, such as web-based applications, especially cloud hosted solutions.

How SAML Works

SAML SSO works by transferring the user’s identity from one place (the identity provider) to another (the service provider). This is done through an exchange of digitally signed XML documents.

Consider the following scenario: A user is logged into a system that acts as an identity provider. The user wants to log in to a remote application, such as a support or accounting application (the service provider). The following happens:

  1. The user accesses the remote application using a link on an intranet, a bookmark, or similar and the application loads.
  2. The application identifies the user’s origin (by application subdomain, user IP address, or similar) and redirects the user back to the identity provider, asking for authentication. This is the authentication request.
  3. The user either has an existing active browser session with the identity provider or establishes one by logging into the identity provider.
  4. The identity provider builds the authentication response in the form of an XML-document containing the user’s username or email address, signs it using an X.509 certificate, and posts this information to the service provider.
  5. The service provider, which already knows the identity provider and has a certificate fingerprint, retrieves the authentication response and validates it using the certificate fingerprint.
  6. The identity of the user is established and the user is provided with app access.

There are many tools and services available to help implement SAML with in your system infrastructure and applications including for your own code as well as third party services that can be integrated.

Coding:

Third Party Services:

Example Implementation with ASP.Net and VB.net

Here is an example of using ComponentSpace’s SAML for ASP.NET component.  A specific URL is called for the login and the XML assertion data is signed using X509 Certificates for security purposes.

A X509 certificate is the public part of the SSL that we install for websites. You can download it from the browser’s certificate view when you have the website open for example.

The Identity Provider (IDP) in this case could be a link off an internal web application.  When the user clicks that link to a page on the external system, a SAML response is submitted to the external system.  The external system then captures the response, parses the XML and authenticates it as follows:

  1. The response is captured
  2. It is verified using the X509 certificate
  3. Encryption of assertions is optional. Some implementations may not send encrypted assertions so we simply verify the source using the X509 certificate. Some implementations will use encryption and in that case, they must use your X509 certificate because only then will you be able to decrypt it using your private key.
  4. Once the data is retrieved from SAML response which typically includes an agreed upon identifier of the user that is used by both parties – the user can be validated against your system and granted access.

Here is sample code using ASP.Net, VB.Net and the ComponentSpace tools.

Imports System.Configuration
Imports System.Collections
Imports System.Security.Cryptography.X509Certificates
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Xml
Imports System.Security
Imports ComponentSpace.SAML2
Imports ComponentSpace.SAML2.Assertions
Imports ComponentSpace.SAML2.Protocols
Imports ComponentSpace.SAML2.Bindings
Imports ComponentSpace.SAML2.Profiles.ArtifactResolution
Imports ComponentSpace.SAML2.Profiles.SSOBrowser
Imports System.Collections.Generic

Public Class SAMLLogin

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        Try

            'Receive the SAML response.
            Dim samlResponse As SAMLResponse = Nothing
            Dim relayState As String = Nothing
            ReceiveSAMLResponse(samlResponse, relayState)

        Catch exception As Exception

            Throw exception.Message

        End Try

    End Sub


    'Function to Process SAML Response.

    Private Sub ReceiveSAMLResponse(ByRef samlResponse As SAMLResponse, ByRef relayState As String)

        'Start of code block to receive response

        Dim CertificateFile As String = CERTIFICATEPATH
        Dim PrivateKey As String = PASSWORD
        ' Receive the SAML response.
        Dim samlResponseXml As XmlElement = Nothing
        ServiceProvider.ReceiveSAMLResponseByHTTPPost(Request, samlResponseXml, relayState)

        'End of code block to receive response


        'Start of block to verify the response signature

        If SAMLMessageSignature.IsSigned(samlResponseXml) Then
            Dim x509Certificate As X509Certificate2 = DirectCast(LoadCertificate(CertificateFile, Nothing), X509Certificate2)
            If Not SAMLMessageSignature.Verify(samlResponseXml, x509Certificate) Then
                lblError.Text = "The SAML response signature failed to verify."
                Exit Sub
            End If
        End If

        'End of code block to verify the response signature


        'Start of code block to initial (serialize) SAML response object from response

        samlResponse = New SAMLResponse(samlResponseXml)
        If Not samlResponse.IsSuccess() Then
            lblError.Text = "Received error response"
            Exit Sub
        End If

        'End of code block to initial (serialize) SAML response object from response


        'Extract the asserted identity from the SAML response

        Dim samlAssertion As SAMLAssertion = Nothing

        Dim DecryptedAssertionXML As XmlElement = Nothing

        Dim EncryptedAssertionXML As EncryptedAssertion = Nothing

        If samlResponse.GetEncryptedAssertions().Count > 0 Then 'Check if the response contained assertions

            Dim x509Certificate As X509Certificate2 = DirectCast(LoadCertificate(CertificateFile, PrivateKey), X509Certificate2) 'Load certificate

            EncryptedAssertionXML = samlResponse.GetEncryptedAssertions()(0) 'Get encryption assertions

            DecryptedAssertionXML = EncryptedAssertionXML.DecryptToXml(x509Certificate) 'Decrypt assertions

            If Not SAMLAssertionSignature.Verify(DecryptedAssertionXML) Then  'Verify decrypted  assertions

                lblError.Text = "Signed assertion failed to verify." 'Signature of assertion invalid

                Exit Sub

            Else

                samlAssertion = New SAMLAssertion(DecryptedAssertionXML)  'If signature valid, serialize the assertion i.e. initiate a class using xml

            End If

        Else 'Error when no assertions found in the response

            lblError.Text = "No assertions in response"

            Exit Sub

        End If

        If Not AssertionIDCache.Add(samlAssertion) Then 'Enforce single use of the assertion. Add assertion to a cache so it cannot be reused.

            lblError.Text = "The SAML assertion has already been used"  'Error when same assertion is already used before

            Exit Sub
        End If

        'At this stage, we have successfully retrieved an assertion and decrypted is successfully
        'and have serialized it. Now we can retrieve the user into enclosed and perform a login routine

        Dim logininfo As String = ""

        'Get all attribute statements which are a group of attributes. See image below for an example of attribute statement.

        Dim attrstmts As List(Of AttributeStatement) = samlAssertion.GetAttributeStatements()

        For Each attr As AttributeStatement In attrstmts

            For Each samlAttribute As SAMLAttribute In attr.GetUnencryptedAttributes() 'Navigate through all attributes to find the ones we need

                If samlAttribute.Name.ToLower = "logininfo" Then 'Attribute found

                    For Each attributeValue As AttributeValue In samlAttribute.Values

                        logininfo = attributeValue.ToString 'Get the value of the attribute

                    Next

                End If

            Next

        Next

        If logininfo.Trim.Length > 0 Then

            PerformLoginRoutin(logininfo) 'Perform login routine

        Else

            lblError.Text = "Blank logininfo was retrieved." 'Error when required attribute could not be retrieved or invalid

        End If

    End Sub

    Private Function LoadCertificate(ByVal fileName As String, ByVal password As String) As X509Certificate2

        Try

            Return New X509Certificate2(fileName, password, X509KeyStorageFlags.MachineKeySet)

        Catch exception As Exception

            Throw exception

        End Try

    End Function

End Class

 

 

Sample SAML XML

saml

 

SAML Glossary

Assertion: This is data provided by the IdP that provides the following statements to the providing service:

  • Authentication Statement – The user specified in the assertion was authenticated successfully and the specific time stamp.
  • Attribute Statements – Provides the attribute values for the user.  Specifically, the NameID must be provided as that is the username, but the other attributes are optional.
  • Authorization Decision Statements – These declare that a request to allow access to the assertion subject has been approved or denied.

Assertion Consumer Service (ACS): This is the URL end point of the service provider that is responsible for receiving and parsing SAML assertions.

Attribute: Defines the data about a user including items like username, first name, ID, etc.

Default Relay State: This defines the URL that a user will be sent to after successful authentication.

Endpoint: The specific URL’s used by Service Providers (SP) and Identity Providers (IdP) to communicate to one another.

Identity Provider (IdP): This is the authority responsible for verifying and asserting a user’s identity and access.

Metadata: Defines the set of information to be supplied between the Identity Provider (IdP) to the Service Provider (SP).  It is structured in xml format.

NameID: A required attribute within the assertion data that specifies the username.

Service Provider (SP): This is the service that the user is requesting to access.

Single Sign On URL: This is the URL endpoint that is responsible for handling SAML transactions.