Categories
Bloggers
Blogs RSS feed

Extend Sitefinity security. Add a custom claim

by Nikola Zagorchev

You can easily extend Sitefinity logic by adding custom claims and validating them using your custom logic. This will help you make sure that certain conditions are met when a request comes in and becomes authorized either by the user providing credentials or using an alternative way to sign on - for example Windows Authentication. You can add a custom claim when the Simple Web Token is being build. In order to override the method that is responsible for Sending the SWT, you should create custom SecurityTokenServiceHttpHandler inheriting from the default one. This way you can override the SendSimpleWebToken method from the service handler:

public class CustomSecurityTokenServiceHttpHandler : SecurityTokenServiceHttpHandler
    {
        protected override void SendSimpleWebToken(HttpContextBase context, Telerik.Sitefinity.Security.Model.User user, RequestMessage reqMessage)
        {
            // Create principal from current user
            var principal = new ClaimsPrincipal(new[] { new SitefinityIdentity(user, true) });
            // My claim
            Claim myClaim = new Claim(ClaimTypes.NameIdentifier, "123456789");
            // Add my claim
            principal.Identities[0].Claims.Add(myClaim);
            // Generate token
            var token = ClaimsManager.BuildSimpleWebToken(principal, reqMessage.Realm);
 
            // base logic
            ...
        }
    }

In order to register your custom service handler and use it in your Sitefinity application, you should replace the default handler in the RoutesTable. This could be done the following way:

public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            Telerik.Sitefinity.Abstractions.Bootstrapper.Initialized += new EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized);
        }
 
        void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        {
            if (e.CommandName == "Bootstrapped")
            {
                var routesCollection = System.Web.Routing.RouteTable.Routes;
                var path = Telerik.Sitefinity.Security.Claims.Constants.LocalService + "/{*Service}";
                var route = routesCollection
                    .Where(r => r.GetType() == typeof(System.Web.Routing.Route)
                        && (r as System.Web.Routing.Route).Url == path)
                        .FirstOrDefault();
 
                if (route != null)
                {
                    var index = routesCollection.IndexOf(route);
                    if (index > -1)
                    {
                        var currentRoute = routesCollection[index] as System.Web.Routing.Route;
                        var routeNew = new RouteHandler<CustomSecurityTokenServiceHttpHandler>();
                        currentRoute.RouteHandler = routeNew;
                    }
                }
            }

We find the default route and modify the route handler to use our custom one.

In order to validate the added claim, the SWTSecurityTokenHandler should be overriden.

The ValidateToken method could be customized to find and validate our claim:

public class CustomSWTSecurityTokenHandler : SWTSecurityTokenHandler
    {
        public override Microsoft.IdentityModel.Claims.ClaimsIdentityCollection ValidateToken(System.IdentityModel.Tokens.SecurityToken token)
        {
            var swt = token as SimpleWebToken;
 
            if (swt == null)
            {
                throw new InvalidOperationException("Token not SimpleWebToken");
            }
 
            var myClaim = swt.Claims.Last();
            bool isValid = true;
 
            if (!isValid)
            {
                throw new UnauthorizedAccessException("Unauthorized");               
            }
 
            return base.ValidateToken(token);
        }
    }

Register the CustomSWTSecurityTokenHandler in the web.config. Find the microsoft.identityModel section and claimsAuthenticationManager, replace the default SWTSecurityTokenHandler with your custom class:

<claimsAuthenticationManager type="Telerik.Sitefinity.Security.Claims.SFClaimsAuthenticationManager, Telerik.Sitefinity"/>
      <securityTokenHandlers>
            <add type="SitefinityWebApp.Security.CustomSWTSecurityTokenHandler, SitefinityWebApp" />
      </securityTokenHandlers>

Here is a video demonstration of the above handlers:

Unable to display content. Adobe Flash is required.

You can download the files from here: Security

Leave a comment