Umbraco 9 Custom Membership using Cookie Authentication

Umbraco 9 is the new release of Umbraco and it uses .NET 5 rather than .Net Framework 4.x, and as such, most of the coding Behind the scenes has changes quite a bit, this means that you'll most likely have to also update your codes if you plan on migrating tot he latest version. Authentication being the big one. 

In previous Umbraco implementations you could get away with using the default authentication providers and pulling your own custom cookie, but it's not as simple as that now as you need to hook into the identity services.

Here's a quick example of an extension method that you can use to implement Cookie based authentication in Umbraco 9:

public static class UmbracoExtensions
{
    public static IUmbracoBuilder AddMemberCustomAuthentication(this IUmbracoBuilder builder)
    {
        // Register MemberCustomLoginProviderOptions here rather than require it in startup
        builder.Services.ConfigureOptions();

        builder.AddMemberExternalLogins(logins =>
        {
            logins.AddMemberLogin(
                memberAuthenticationBuilder =>
                {
                    String strSchemeName = memberAuthenticationBuilder.SchemeForMembers(CookieAuthenticationDefaults.AuthenticationScheme);

                    builder.Services.AddTransient<CustomCookieAuthenticationEvents>();

                    memberAuthenticationBuilder.AddCookie(strSchemeName, objCookieAuthenticationOptions =>
                    {
                        objCookieAuthenticationOptions.Cookie.Name = strSchemeName;
                        objCookieAuthenticationOptions.LoginPath = "/";
                        objCookieAuthenticationOptions.EventsType = typeof(CustomCookieAuthenticationEvents);
                    });

                    builder.Services.AddAuthentication(options =>
                    {
                        options.DefaultAuthenticateScheme = strSchemeName;
                    });
                    builder.Services.AddAuthorization();
                });
        });
        return builder;
    }
}

As you can see it adds the cookie authentication requirements within the AddMemberExtenralLogins method and specifies a CustomCookieAuthenticationEvents class to handle validation of the specified cookie, as an optional extra we also set cookies as the default authentication provider for members.

public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
    private readonly IMemberService _memberService;
    private readonly ILogService    _logService;

    public HexCookieAuthenticationEvents(IMemberService objMemberService, ILogService objLogService)
    {
        // Get the database from registered DI services.
        _memberService  = objMemberService;
        _logService     = objLogService;
    }

    // Sign user out if their password has changed, their account has been disabled or they've been locked out.
    public override async Task ValidatePrincipal(CookieValidatePrincipalContext objContext)
    {
        ClaimsPrincipal objUserPrincipal = objContext.Principal;

        // Look for the LastChanged claim.
        string      strLastChanged      = (from c in objUserPrincipal.Claims where c.Type == "LastChanged" select c.Value).FirstOrDefault();
        DateTime    dtmLastChanged;     DateTime.TryParse(strLastChanged, out dtmLastChanged);
        Member      objCurrentMember    = _memberService.GetMemberByUsername(objUserPrincipal.Identity.Name); // This potentially calls a lot so we need to validate from cache.

        if (objCurrentMember == null)
        {
            _logService.Alert(Enums.AlertType.Warning, "You have been signed out because the user account could not be found.", "Your account does not exist");
            await SignOut(objContext);
        }
    }

    public override Task SigningOut(CookieSigningOutContext context)
    {
        return base.SigningOut(context);
    }

    private async Task SignOut(CookieValidatePrincipalContext objContext)
    {
        objContext.RejectPrincipal();

        await objContext.HttpContext.SignOutAsync();
    }
}

And that's essentially it, you may want to implement a bit more security but that will get you started.


Published at

Tags: Umbraco,Authentication,Cookies

Luke Alderton

Comments

Share with
Tags
Latest Comments
By Mark Gentry on Windows Server 2019 - Change product key does nothing
20 Aug 2021, 03:30 AM
By Cathy on In-Place Upgrade for a Windows Server domain controller
31 Jul 2021, 18:28 PM
By Mr. Greymatter on Raspberry Pi - Running Java app on Raspbian
16 Feb 2021, 07:35 AM
By Mikko Seittenranta on Xamarin Forms multiple instances of same app open
16 Feb 2021, 04:34 AM
By Andrew on Auto/Custom height on Xamarin Forms WebView for Android and iOS
22 Jan 2021, 22:15 PM
By Nick on Raspberry Pi - Running Java app on Raspbian
14 Oct 2020, 19:37 PM
By Ivan on Fixed: Value cannot be null Parameter Name: source
15 Sep 2020, 19:47 PM
By Anand on Raspberry Pi - Bluetooth using Bluecove on Raspbian
7 Sep 2020, 16:53 PM
Categories
App Development
Event
Game Development
Mapping
Modelling
Programming
Review
Robotics
Tutorial
Web Development