Multiple Authentication Schemes

Tuesday, April 23, 2019

By: Chris Dunn

If you haven't read my post on cookie authentication in .net core, I suggest you do that now since I will be referencing it in the following post.

There will be times when you will want more than one sign in under a web application.  This usually involves a member section and an administrative section of your application.  You could write two separate applications, one for the front-end, and another for the back-end.  Sometimes this is overkill and tricky depending on your deployment infrastructure. 

Finally, you could merge the admin user and members and instead utilize "roles".  If you've looked at all of those options and they don't fit, then we could simply provide two Authentication Schemes for the application.

So, building on my first cookie authentication post's example, let's look at the ConfigureServices method of the StartUp class.  When we are adding our Authentication to the services, where we originally added a single cookie, we can simply add a second cookie with a different scheme name. 

In the code below, the first parameter in the AddCookie method is the Scheme name.  For this example, I called one scheme "admin" for the backend, and one "member" for the front-end.  I have also pointed to the associated paths for login and denied as well as a unique cookie name for the scheme.

//Add cookie authentication configuration
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                 .AddCookie("admin",
                    options =>
                    {
                        options.LoginPath = new PathString("/admin/auth/signin");
                        options.AccessDeniedPath = new PathString("/admin/auth/denied");
                        options.Cookie.Name = "AdminCookieAuth";

                    })
                .AddCookie("member".
                    options =>
                    {
                        options.LoginPath = new PathString("/auth/signin");
                        options.AccessDeniedPath = new PathString("/auth/denied");
                        options.Cookie.Name = "MemberCookieAuth";
                    });

In the Sign In action methods for the AuthControllers for each area, we'll need to specify the scheme name as the first parameter of the HttpContext.SignInAsync method.

                await HttpContext.SignInAsync("admin",
                    principal,
                    new AuthenticationProperties
                    {
                        ExpiresUtc = DateTime.UtcNow.AddMinutes(25),
                        AllowRefresh = false,
                        IsPersistent = false
                    });
                await HttpContext.SignInAsync("member",
                    principal,
                    new AuthenticationProperties
                    {
                        ExpiresUtc = DateTime.UtcNow.AddMinutes(25),
                        AllowRefresh = false,
                        IsPersistent = false
                    });

Now, to protect a controller or action with the Authorize attribute, we now need to provide the sheme we are authorizing instead of an empty attribute. We use Authorize(AuthenticationSchemes = "admin") to indicate the admin scheme. In my example I am placing the administrative back end under a separate area, hence the Area attribute, but you don't need to do so if you organize differently.

    [Area("Admin")]
    [Authorize(AuthenticationSchemes = "admin")]
    public class AdminHomeController : Controller
    {

   }

    [Authorize(AuthenticationSchemes = "member")]
    public class MemberHomeController : Controller
    {

   }

And that's all there is to having more than one sign in for a single web application. In this post i've outlined two schemes but you can obviously have more if you are so inclined.

Tags: c# cookies authentication

Copyright 2019 Cidean, LLC. All rights reserved.

Proudly running Umbraco 7. This site is responsive with the help of Foundation 5.