programming

Custom Authentication Handler .Net Core

September 9, 2020 c#, programming

Custom Authentication Handler .Net Core

The MVC framework for c# has a nice authentication and authorization framework that covers almost all use cases that there are currently. But what if there is an authentication method that you need that it currently does not support?

Custom Authentication handlers are your answers as it can build on top of the current framework. In this document I will go over the very basics of creating a custom authentication handler in C# .Net Core 3.

Creating The Project

Lets start by creating new project in Visual Studio using the ASP.NET Core Web Application template.

Create a new ASP.NET Core Web Application.

Name the project. In this example I decided to name it CustomHandlerTest. On the next screen, ensure that you click Change under Authentication and select Individual User Accounts.

Changing the Authentication Method

Once the project is created and loaded we will want to create two new classes. One called CustomAuthOptions and one called CustomAuthHandler.

The CustomAuthOptions Class

The below class will provide the capability for specifying options for the custom authentication handler. Right now lets just create the Realm string in it. This class also inherits the AuthenticationSchemeOptions class.

The CustomAuthHandler Class

The CustomAuthHandler class is where the magic is handled. Lets start by creating a class that inherits the AuthenticationHandler interface with a type of CustomAuthOptions.

    {

Next we will override the method of HandleChallengeAsync. This method will return a challenge that will cause the browser to prompt a username and password.

        {
            Response.Headers["WWW-Authenticate"] = $"Basic realm=\"{Options.Realm}\", charset=\"UTF-8\"";
            await base.HandleChallengeAsync(properties);
        }

The next method that we will override will be the HandleAuthenticateAsync method. This is the method that will either pass the authentication or cause it to fail. The first three if statements we are ensuring that the authorization header value is valid and that the scheme is "Custom", which is specified at the beginning of the class.

The method decodes the header value and extracts the username and password into their own string values. If the password does not match ThePassword and the username of michael, it will cause the authentication method to fail.

            string userAndPassword = Encoding.UTF8.GetString(headerValueBytes);
            string[] parts = userAndPassword.Split(':');
            if (parts.Length != 2)
            {
                return AuthenticateResult.Fail("Invalid Basic authentication header");
            }
            string user = parts[0];
            string password = parts[1];
      
            if(user != "michael" || password != "ThePassword")
            {
                return AuthenticateResult.Fail("Invalid username or password");
            }

The next section of the code setups a new claim and passes the ticket up the chain. The full code of this method is below.

Telling The Framework About Your Custom Handler

Now is the time to tell the MVC framework about your custom authentication handler. We will want to open the Startup.CS and add the following lines under ConfigureServices().

Testing

Now we can create a class or add a method to a controller that has the [Authorize] attribute. I created a Test method under the home controller. Added code to convert the claims into a json and output the Content to a string.

Testing the code from Postman

The Test method returns a string and with the custom authorization header it will be easiest to test the authentication handler from PostMan. Launch your project and record the URL and port that it uses to take you to the home page. Launch Postman and perform a get to [URL]/home/test and if everything is setup correctly it will return a 401 with an WWW-Authenticate header.

Now to test the authentication method we can add the Authorization header to the GET request. The header will have the value of Custom bWljaGFlbDpUaGVQYXNzd29yZA== The word Custom tells the project that this is authentication scheme of Custom which we specified in the startup class. The random strings of text is a base64 encoded string of michael:ThePassword. Once this is setup perform a GET request.

If everything is okay, you will receive an 200 OK status code and receive a body of "You have received the test message." Along with the claims in a JSON format.

This code will get you started on a custom authentication handler. You could have it check against several different sources or perform some mathematical magic to create a puzzle to allow authentication.