I recently spent some time with a customer who wanted to use PingFederate Server with Episerver. After some initial Googling I could see PingFederate Server is a single sign on (SSO) server which is part of the Ping Identity suite of products. The image from the Ping Identity site implied Episerver could act as a Web App so it looked promising:

©2000-2017 Ping Identity Corporation

Most importantly for me it I noted it coud configured to support the WS-Federation protocol (WS-FED). This means it should be easy to set an Episerver site using the standard infrastructure we have to set up federated security in Episerver.

So this post is a knowledge share to ensure I have notes in case I need to do this it again in the future. 

The initial proof of concept was planned as follows:

  1. Set up and configure an Episerver site in Episerver Digital Experience Cloud Service and ensure it runs over SSL
  2. Configure an end point for the Episerver site in PingFederate to use WS-FED
  3. Configure Episerver to accept role and user claims from PingFederate to configure our security in Episerver edit/admin mode

The implementation we were looking to achieve was as follows:

The execution flow in the steps above are as follows:

  1. User requests a URL from Episerver that requires authentication
  2. Internally Episerver generates a 401 and responds with a redirect (302) to request authentication from PingFederate
  3. The user's browser responds to the redirect and navigates to the PingFederate server
  4. PingFederate authenitcates the user and responds with a set of claims written to the response
  5. The user's browser processes the response from PingFederate and (using Javascript) creates a form POST request to Episerver to process the claims
  6. Episerver authenticates the POST containing the claims, authenticates the user and responds with the original URL requested in step 1 

The PingFederate Server part

  • Ping Identity server had to be configured to support WS-FED protocol as the instance we were using did not have it enabled by default.
  • Federation meta data xml had to be exported manually (see notes of interest)
  • The user's Active Directory membership was mapped in the PingFederate Server configuration and issued as a claim at authentication time

The Episerver part

The Episerver part was remarkably simple and followed the standard guideline for integrating implementing federated security in Episerver.

I implemented a custom ISynchronizingUserService to create custom roles based on the Active Directory attributes that were issued by the PingFederate Server as claims. The code for this is here but note it was written in haste during the POC and your implementation may extend/change this:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using EPiServer.Async;
using EPiServer.Security;

namespace PingFed.Auth
{
    public class PingFedSynchronizingUserService : ISynchronizingUserService
    {
        private readonly TaskExecutor _taskExecutor;

        public PingFedSynchronizingUserService(TaskExecutor taskExecutor)
        {
            _taskExecutor = taskExecutor;
        }

        public virtual Task SynchronizeAsync(ClaimsIdentity identity, IEnumerable additionalClaimsToSync) =>
            _taskExecutor.Start(new Action(delegate
            {
                this.SynchronizeUserAndClaims(identity, additionalClaimsToSync);
            }));

        internal virtual void SynchronizeUserAndClaims(ClaimsIdentity identity, IEnumerable additionalClaimsToSync)
        {
            foreach (var claim in identity.Claims)
            {
                if (claim.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/WS-Federation")
                {
                    List claimValues = new List(claim.Value.Split(','));
                    foreach (var claimValue in claimValues)
                    {
                        if (claimValue.StartsWith("CN="))
                        {
                            identity.AddClaim(new Claim(ClaimTypes.Role, claimValue.Replace("CN=", string.Empty)));
                        }
                    }
                }
                if (claim.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")
                {
                    identity.AddClaim(new Claim(ClaimTypes.UserData, claim.Value));
                    identity.AddClaim(new Claim(ClaimTypes.Name, claim.Value));
                }
            }
        }
    }
}

Points of interest and advice

When working on a proof of concept such as this its always best to make the ivestment in time and get people with the right knowledge in the room. From the customer side we had a PingFederate Server expert, from the Episerver side I had myself and finally we had the partner who will be performing the implementation for the customer. This ensured knowledge was transferred immediately and that we collaborated quickly to build out the proof of concept without the traditional email/ticket bounce that can sometimes hinder progress. 

The PingFederate the server itself was on the corporate network and totally inaccessible from the outside world. This meant the XML meta data was not accessible directly from Episerver. So it has to be manually exported and made available to Episerver.

This also meant we were authenticating an Episerver instance running in the public cloud against an internal identity service which really delivered on a "best of of both" approach where the Cloud is used to deliver a customer's site whilst all authentication and indentity is managed internally.

Futher reading

The following links are useful information about federated security in Episerver and PingFederate:

Conclusion

The entire proof of concept took a couple of hours and if you ignore the inherent complexities of a complex indentity infrastructure was implemented without fuss using standard protocols and technologies.

I personally think every new project should consider federated security as it cleanly separates authentication concerns and ensure customers stay in control of their user's identities whilst allowing Episerver implementors to concentrate on the Episerver implementation components.


Comments

comments powered by Disqus