Sitecore 9 comes with nifty new configurations for federated authentication using a variety of identity providers, including SAML providers. If you’re stuck on Sitecore 8 for a little while, though, SAML authentication is still a custom implementation.
With the right tools, however, the task is not as daunting as it may initially seem. We at SymSoft set up a simple proof-of-concept to demonstrate that the integration can be fairly simple depending on the requirements. For us, the setup was as follows:
- We had a SAML Identity Provider (IDP) that would accept authentication requests.
- Users with the same usernames would already exist in Sitecore (we weren’t pulling users in from the IDP, just authenticating them).
- Roles would also be defined in Sitecore, and the Sitecore users would be added to those roles appropriately for permissions purposes (we did not use any SAML assertions to determine what level of permissions would be needed in Sitecore).
I won’t go into too many details about how SAML or SAML SSO works. If you’d like detailed information about that, you can find tons of resources online. At the highest level, there are two parties involved for SAML authentication, namely a Service Provider (Sitecore in this case), and an Identity Provider (Tivoli Identity Manager in our case). Here’s an overly simplified process of what should happen:
- The Service Provider (SP) initiates a request to the Identity Provider (IDP) for authentication. For some IDPs, a login page is presented. Other IDPs allow for passing local credentials through.
- Once logged in, the IDP initiates a callback to the SP, letting the SP know that the authentication was successful. The SP then decides what to do with that information (e.g. logging the user into the application).
In order to bypass the intricacies of SAML for this POC, we used a library called ComponentSpace SAML: https://www.componentspace.com/SAMLv20.aspx. The library is basically a .NET wrapper for SAML, so that you just have to invoke methods using the library rather than developing all the SAML methods yourself. It really makes things simple.
Here are the prerequisites we performed before authentication could happen. You can get more information about this part of SAML as well using online resources.
- We generated the Service Provider metadata using ComponentSpace tools. This metadata was then provided to the Identity Provider in order to register the Service Provider (Sitecore) along with the callback URLs that would need to be called by the Identity Provider (Tivoli) on successful login.
- We then followed ComponentSpace documentation to create the appropriate saml.config file in Sitecore that contained information about the Identity Provider and the URLs for IDP authentication.
Okay, now for the sample code in Sitecore. First, you’ll need the code that initiates the SSO from the Service Provider (Sitecore).
public ActionResult SingleSignOn(string url) { // To login at the service provider, initiate single sign-on to the identity provider (SP-initiated SSO). string ssoServiceUrl = WebConfigurationManager.AppSettings["IDPSSOServiceUrl"]; string idpName = WebConfigurationManager.AppSettings["IDPName"]; SAMLServiceProvider.InitiateSSO(Response, null, idpName, null, null, ssoServiceUrl + "?CustomData=" + url); return new EmptyResult(); }
Then, the Identity Provider will do its thing and will invoke a callback method at the Service Provider (Sitecore). Here’s the sample code for that callback method.
public ActionResult AssertionConsumerService() { bool isInResponseTo = false; string partnerIdP = null; string userName = null; IDictionary<string, string> attributes = null; string targetUrl = null; // Receive and process the SAML assertion contained in the SAML response. // The SAML response is received either as part of IdP-initiated or SP-initiated SSO. SAMLServiceProvider.ReceiveSSO(Request, out isInResponseTo, out partnerIdP, out userName, out attributes, out targetUrl); // If no target URL is provided, provide a default. if (targetUrl == null) { targetUrl = "~/sitecore/shell/sitecore/client/Applications/Launchpad"; } // Login to Sitecore automatically using the asserted identity. Sitecore.Security.Authentication.AuthenticationManager.Login("sitecore\\" + userName, true, true); // Save the attributes (optional if you have attributes from the IdP). Session["AuthorizationData"] = attributes; // Redirect to the target URL specified by the IdP, or the default. return Redirect(targetUrl); }
And that’s pretty much it. In summary, you have a page in Sitecore that initiates SSO with the Identity Provider (code snippet 1) and then you log the user into Sitecore programmatically when the Identity Provider invokes the callback method in Sitecore (code snippet 2). As mentioned already, I know that I have skipped many internals of SAML for the purposes of this blog post, but there’s plenty of resources online to help with that.