Adding a Logout Link to the Quick Navigator in Optimizely CMS 12

Here's a quick code snippet for adding a logout link to the Quick Navigator menu in Optimizely CMS 12. This is done a bit differently in CMS 12, since the logout page is using Razor Pages instead of WebForms, and the new logout method requires an antiforgery token.

Extending the Quick Navigator Item Provider

First, we'll need a class that implements the IQuickNavigatorItemProvider interface:

public class ExtendedQuickNavigatorItemProvider : IQuickNavigatorItemProvider
{
    private readonly UIPathResolver _uiPathResolver;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IAntiforgery _antiforgery;
    private readonly IOptions<AntiforgeryOptions> _antiforgeryOptions;
    private readonly IOptionsMonitor<CookieAuthenticationOptions> _cookieAuthenticationOptions;

    public ExtendedQuickNavigatorItemProvider(
        UIPathResolver uiPathResolver,
        IHttpContextAccessor httpContextAccessor,
        IAntiforgery antiforgery,
        IOptions<AntiforgeryOptions> antiforgeryOptions,
        IOptionsMonitor<CookieAuthenticationOptions> cookieAuthenticationOptions)
    {
        _uiPathResolver = uiPathResolver;
        _httpContextAccessor = httpContextAccessor;
        _antiforgery = antiforgery;
        _antiforgeryOptions = antiforgeryOptions;
        _cookieAuthenticationOptions = cookieAuthenticationOptions;
    }

    public int SortOrder => 50;

    public IDictionary<string, QuickNavigatorMenuItem> GetMenuItems(ContentReference currentContent)
    {
        var menuItems = new Dictionary<string, QuickNavigatorMenuItem>();

        var logoutUrl = _cookieAuthenticationOptions.Get(IdentityConstants.ApplicationScheme)?.LogoutPath.Value ?? _uiPathResolver.CombineWithUtil("Logout");
        logoutUrl = $"{logoutUrl}?{_antiforgeryOptions.Value.HeaderName}={_antiforgery.GetAndStoreTokens(_httpContextAccessor.HttpContext).RequestToken}";
        menuItems.Add("qn-logout", new QuickNavigatorMenuItem("/shell/cms/menu/logout", logoutUrl, null, "true", null));

        return menuItems;
    }
}

This item provider builds the logout url, including the antiforgery token, and adds it to a dictionary of menu items. The antiforgery token is required for logging out, otherwise, the logout method will return a "Bad Request" error (HTTP 400 response status code).

Note: The above code snippet is pretty much the same as how it's created within the edit UI.

Registering the Item Provider

To use this extended item provider, we'll just need to register it in our Startup.cs class:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddTransient<IQuickNavigatorItemProvider, ExtendedQuickNavigatorItemProvider>();
        ...
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
    }
}

And that's it! Now you'll have a handy logout link available in the Quick Navigator!