SAML 2.0 is an authentication protocol, an agreed-upon way to transfer authentication information between parties. It was approved as an OASIS standard in 2005, and there are SAML Protocol Documents with details about the protocol.
The protocol is complex (the core document alone is 86 pages) and has a wide range of capabilities. In this post, I’ll scratch the surface of SAML 2.0 by summarizing the main things I learned when setting up SAML authentication for our application.
This post will focus on integrating with the SAML protocol—not how to integrate with SAML on a specific platform. If you happen to be working with Rails, I suggest you check out my coworker’s post on integrating SAML with Rails.
With single sign-on, a user can enter their credentials once and then get access to many different systems sharing the same identity prover. The user doesn’t need to keep track of multiple usernames and passwords to use systems that are related to each other.
When a user logs in the first time, the identity provider creates a session for that user. From then on out, if a service provider sends a user to the identity provider to be authenticated, the identity provider already has the session for the user and does not need to ask the user for credentials.
SAML is one option for implementing single sign-on. If you would like to know how SAML compares to other single sign-on options, check out this post on single sign-on protocols.
The identity provider
According to the OASIS glossary, an identity provider “creates, maintains, and manages” identity information and provides authentication to other service providers. The identity provider is responsible for looking up a user given their login credentials.
The service provider(s)
OASIS defines the service provider as “a system entity where the system entity provides services.” That’s a broad definition, but for good reason–the service provider can be any sort of application needing authentication.
In this post, we’ll talk about two service providers that hook up to the same identity provider: one is a website with soup recipes, and one is a website with sandwich recipes (these are super-secret family recipes, so we want the user to have to authenticate before seeing them). Since the service providers share an identity provider, a user will be able to log in to both sites with the same username/password.
This is defined as a “person who makes use of a system and its resources for any reason.” In our case, this would be a hungry person who needs those soup and sandwich recipes.
The SAML Login Flow
Initial SAML login flow
Let’s jump ahead and assume the soup & sandwich websites are set up to use a SAML identity provider. What would the user sign-on process look like?
- Jimmy (the user) gets home from work and desperately wants a bowl of warm soup.
- Jimmy tries to visit the soup recipe site.
- He is not yet logged in, so he does not have a session on the soup site. The soup site is configured with an identity provider URL. It uses that URL to redirect the user to the identity provider.
- The identity provider verifies the authentication request from the soup site.
- Because Jimmy does not yet have an authenticated session with the identity provider, he is prompted for his credentials. The identity provider looks up Jimmy’s credentials and then creates a session for him. The service provider initiating the request (i.e. the soup site) is associated with Jimmy’s session.
- Now that the identity provider has verified Jimmy’s credentials and created a session for him, it needs to send a SAML assertion indicating success back to the soup site. There are a couple options for doing this. The identity provider could post back to the service provider with the assertion as the body. Alternatively, the identity provider could be configured to redirect back to the service provider with all the assertion information in the redirect URL. Though HTTP redirect might work great for short SAML assertions, the length of a redirect URL is limited, making this approach unreliable for longer responses. So, let’s assume the identity provider has been configured to post the assertion to the service provider.
- A post request will be sent to the soup site’s ACS (Assertion Consumer Service URL). The ACS url is the URL responsible for accepting SAML assertions from the identity provider. The identity provider stores the service provider ACS URLs that it can POST to. Let’s assume the identity provider has been configured with the soup site’s ACS URL.
- The SAML assertion includes at least a name ID identifying the user and a session index identifying the session that was just created.
- The service provider receives and verifies the SAML assertion. The service provider is configured with the same public key as the identity provider. It uses this public key to verify that the assertion is in fact from the identity provider.
- The service provider then extracts user information from the SAML assertion. It is the service provider’s responsibility to redirect the user to the appropriate place in the application and to decide what to do with the user information (sign in the user, grant the user specific permissions, save the user information, etc.). To persist the user’s login, the service provider will most likely create a session for the user. The created session should store both the session index and the user name ID from the SAML assertion. Having these things handy will be important when signing out.
Jimmy is now signed in and has a session for the soup site. He can finally access his favorite soup recipes. He never logged in to the soup site directly, but instead gave his credentials to the identity provider. The identity provider told the soup website the Jimmy had an account and perhaps provided some additional information about who Jimmy is. The soup website used that information to create a session for Jimmy and make decisions about what Jimmy could and couldn’t do.
SAML login with existing identity provider session
But what if Jimmy wants to make a sandwich to go with his soup? Let’s assume the sandwich website uses the same identity provider as the soup website. The authentication flow would look something like this:
- Jimmy tries to sign in to the sandwich site.
- Jimmy is not logged in to the sandwich site, so he does not have a session. He is redirected to the identity provider.
- The identity provider already has an authenticated session for Jimmy. It looks up Jimmy’s session and updates the session to include details about the sandwich site. Jimmy’s identity provider session is now associated with both the soup site and the sandwich site.
- The identity provider posts a SAML assertion with the session and user information to the sandwich site.
- Similarly to the soup site, the sandwich site extracts the necessary information from the SAML assertion and creates a session for Jimmy.
Now Jimmy is signed in to both the sandwich site and the soup site. When Jimmy first attempted to log in, the soup site redirected him to the identity provider. Since Jimmy did not yet have an identity provider session, he had to enter his credentials.
Next, Jimmy signed into the sandwich site. He was again redirected to the identity provider, but this time he already had an identity provider session so did not have to re-enter his credentials. Instead, the identity provider just added a “note” to Jimmy’s session, saying that Jimmy was now logged into the sandwich site as well the soup site. After making this update, the identity provider sent Jimmy straight back to the sandwich site.
The ease of logging in to the sandwich site demonstrates the efficiency of single sign-on. After entering his credentials once, Jimmy can seamlessly be authenticated with any service that uses the same identity provider. He can sign in once for the soup site and then access the soup side, the sandwich site, and any other application using the same identity provider (granted he has permission to view them).
The SAML Logout Flow
Let’s say Jimmy wants to sign out so his friends cannot see his super-secret sandwich and soup preferences. When he clicks the “sign out” button, Jimmy wants to sign out from both the sandwich site and the soup site.
When Jimmy first signed in, the identity provider created a session for Jimmy. Both the soup site and the sandwich site also created sessions for Jimmy. These service provider sessions store–at minimum–Jimmy’s name ID and the session index.
How does Jimmy get rid of all these sessions and sign out from both sites at once? Here’s the process for single sign-out:
- Jimmy goes to either the soup site or the sandwich site and clicks “Log Out.” Let’s say he starts with the sandwich site.
- The sandwich has Jimmy’s name ID and identity provider session index stored in its session. It creates a logout request asking the identity provider to logout the user with a corresponding name ID and session index.
- The identity provider validates the logout request. If valid, the identity provider looks up the session by the session index and name ID. On finding the session, the identity provider sends a logout request to all services providers associated with the session (except the service provider initiating the request). In our case, a logout request would be sent to the soup site.
- The soup site validates the logout request, invalidates its user session, and sends a logout response back to the identity provider.
- The identity provider invalidates its session for the given name ID and session index. It then sends a logout response to the service provider that initiated this whole process (the sandwich site).
- The sandwich site destroys Jimmy’s session.
- Jimmy can finally start making his soup and sandwich.
Just like signing on once told all the service providers associated with the identity provider about Jimmy, so clicking the sign-out button once tells all service providers that Jimmy no longer should have access.
For an organization that has many different portals all requiring authentication, this single sign-on/sign-out with SAML means that one can access whatever one needs after entering login information once. And, at the end of a full day, one can sign out once and not worry about logging out from each individual portal.