I Made a Package for the Unrestricted Boost Operation Known Issue

This week Sitecore released a known issue stating, “Any Sitecore Client user is capable of performing boost and kick operations after the maximum number of allowed users has been reached”. A starting point for the code fix was provided, but teams will need to complete it, then package and deploy it. I've done that and uploaded the package for anyone who needs it. 

 

What's the Problem?

Sitecore licensing allows for a certain number of concurrent client Users. You can check this value in the Content Editor (among other places) by clicking on Home -> Licenses -> SiteCore.EditorUser.

 

If the maximum number of Users has been exceeded, the person logging in will be redirected to the License Options page (/sitecore/client/Applications/LicenseOptions/StartPage) where they can temporarily boost this number.

 


Here's the problem. Anyone can do this.

 

How to Restrict the Boost Capability to Administrator

Sitecore started us off with the code sample on the known issue page but left out the GetBoostUrl for administrators. They started with a patch file, which I modified to match the assembly name in the provided project (below).

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
    <sitecore role:require="Standalone or ContentManagement or XMCloud">
        <pipelines>
            <initialize>
                <processor type="Sitecore.Support.Mvc.Pipelines.Initialize.InitializeRedirectToBoostRoute, SitecoreFundamentals.InitializeRedirectToBoostRoute" 
                patch:before="processor[@type='Sitecore.Mvc.Pipelines.Initialize.InitializeCommandRoute, Sitecore.Speak.Client']"></processor>
            </initialize>
        </pipelines>
    </sitecore>
</configuration>

Next, the InitializeRedirectToBoostRoute sets up the BoostUsers controller:

namespace SitecoreFundamentals.InitializeRedirectToBoostRoute.Pipelines
{
    public class InitializeRedirectToBoostRoute
    {
    }
}
namespace Sitecore.Support.Mvc.Pipelines.Initialize
{
    internal class InitializeRedirectToBoostRoute
    {
        public virtual void Process(PipelineArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            this.RegisterRoutes(RouteTable.Routes, args);
        }
        protected virtual void RegisterRoutes(RouteCollection routes, PipelineArgs args)
        {
            string[] namespaces = new string[] { "Sitecore.Support.Client.LicenseOptions.Controllers" };
            routes.MapRoute("RouteName", "api/sitecore/BoostUsers/{action}", new
            {
                controller = "BoostUsers",
                action = "RedirectToBoost",
                id = UrlParameter.Optional
            }, namespaces);
        }
    }
}

Finally, the RedirectToBoost is called instead of the OOTB one. I've also added some logging:

public class BoostUsersController : Controller
    {
        [HttpGet]
        public void RedirectToBoost()
        {
            if (Context.User.IsAuthenticated || !Context.User.IsAdministrator)
            {
                Log.Info($"User {Context.User.Name} is being presented a 401 response.", this);
                base.Response.StatusCode = 401;
            }
            else
            {
                var boostUrl = GetBoostUrl();
                Log.Info($"User {Context.User.Name} is being redirected to {boostUrl}.", this);
                base.Response.Redirect(boostUrl, endResponse: true);
            }
        }

 It is the GetBoostUrl() portion that was not provided in the known issue article.  You can just mimic the URL that's generated by trying it out in your own instance, but I thought it was better to get the method from Sitecore.Client.LicenseOptions.dll -> GetBoostUrl(). knowing what it does, I added the following method to this project:

protected string GetBoostUrl()
{
    var licenseID = SecurityModel.License.License.LicenseID;
    var licensee = SecurityModel.License.License.Licensee;
    var urlString = new UrlString(WebUtil.GetFullUrl(new StartUrlManager().GetStartUrl(Context.User)));
    urlString.Add("inv", "1");
    var urlString2 = new UrlString("http://www.sitecore.net/boost");
    urlString2.Add("url", urlString.ToString());
    urlString2.Add("lid", StringUtil.GetString(new string[]
    {
        licenseID
    }));
    urlString2.Add("host", StringUtil.GetString(new string[]
    {
        WebUtil.GetHostName()
    }));
    urlString2.Add("ip", StringUtil.GetString(new string[]
    {
        WebUtil.GetHostIPAddress()
    }));
    urlString2.Add("licensee", StringUtil.GetString(new string[]
    {
        licensee
    }));
    urlString2.Add("iisname", StringUtil.GetString(new string[]
    {
        WebUtil.GetIISName()
    }));
    return urlString2.ToString();
}

 

Where Can I Get a Package?

I've uploaded the project to my GitHub page here for anyone to use. The packages are included in the sc.package folder with update or WebDeploy options.