How to validate Rest API using Basic Authentication in Web API .Net Core

We are going to implement the Basic Authentication in Asp.Net Core web API. Also, will have a demo, how to access the web API secured by basic auth.

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest

What is Authentication?

Authentication is the process or action of proving or showing something to be true, genuine, or valid. In order to access any secured resource over the internet/intranet, you have to provide the credential. It may be a username, password or secret key, etc.

What is Basic Authentication?

Basic authentication is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization the header that contains the word Basic followed by a space and a base64-encoded string username:password.

 

What we are going to demonstrate in this article?

We are going to implement the Basic Authentication in Asp.Net Core web API. Also, will have a demo, how to access the web API secured by basic auth.

 

Let’s start building project

Note: I am going to use Postman as a client for testing the API

I have created an Asp.Net core 2.0 project called RestApi.Demo Which will have one secure controller called EmployeeController.

Solution structure,Beetechnical.com,Basic Authentication

 

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace RestApi.Demo.Controllers
{
    [Route("api/employee")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        // GET: api/Employee
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

    }
}

 

As you can see in the above code snippet EmployeeControll class does not have any Authorize attribute. Also, it has only one method called Get which will be accessible through API/Employee.

 

Let’s run the project and see what we get in the postman response. As expected you will see the welcome message. Because we have not added any kind of authentication to our WebAPI project.

 

As you can, we could hit the controller and access the result without any issue.

Now, Try to put some authentication on our EmployeeeController

In order to secure your EmployeeController, you have to make a few changes in two places.

  1. You have to decorate the EmployeeController with Authorize attribute.
  2. you have to add authentication module in your WebApi using startup.cs file.
  3. And, you have to specify which authentication scheme you are going to us
  4. Also, you have to provide the implementation of the BasicAuthentication middleware. Which will validate the incoming credential against your database or configuration.

Start with EmployeeController by adding the [Authorize] attribute.

using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace RestApi.Demo.Controllers
{
    [Route("api/employee")]
    [ApiController]
    [Authorize]
    public class EmployeeController : ControllerBase
    {
        // GET: api/Employee
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

    }
}

Jump to the Startup.cs file and method called ConfigureServices.

// This method gets called by the runtime. Use this method to add services to the container.
   public void ConfigureServices(IServiceCollection services)
   {
       services.AddAuthentication("Basic");
       services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
   }

As you can see in line no # we have added services.AddAuthentication(“Basic”) which will tell API that authentication mechanism has been added.

Now, start making changes in the Configure method of a startup.cs file. Here we have to add the basic authentication along with the pipeline before the MVC. Which will validate the incoming credential against your configuration or database.

For the demonstration purpose, I am using a hardcoded value. admin ad username and password.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMiddleware<BasicAuthMiddleware>(new BasicAuthenticationOptions
            {
                Name = "admin",
                Password = "admin"
            });
            app.UseMvc();
        }

BasicAuthMiddleware.cs is the class where we are going to validate the credential. So, Please go through it carefully.

using Microsoft.AspNetCore.Http;
using System;
using System.Linq;
using System.Net;
using System.Security.Principal;
using System.Threading.Tasks;

namespace RestApi.Demo.Core
{

    public class BasicAuthMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly BasicAuthenticationOptions _options;

        public BasicAuthMiddleware(RequestDelegate next, BasicAuthenticationOptions options)
        {
            this._next = next;
            this._options = options ?? throw new ArgumentException("User info can't be null");
        }

        public async Task Invoke(HttpContext context)
        {
            if (CheckIsValidRequest(context, out string username))
            {
                var identity = new GenericIdentity(username);
                var principle = new GenericPrincipal(identity, null);
                context.User = principle;
                await this._next.Invoke(context);
            }
            else
            {
                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }
        }

        private bool CheckIsValidRequest(HttpContext context, out string username)
        {
            var basicAuthHeader = GetBasicAuthenticationHeaderValue(context);
            username = basicAuthHeader.UserName;
            return basicAuthHeader.IsValidBasicAuthenticationHeaderValue &&
                   basicAuthHeader.UserName == this._options.Name &&
                   basicAuthHeader.Password == this._options.Password;
        }

        private BasicAuthenticationHeaderValue GetBasicAuthenticationHeaderValue(HttpContext context)
        {
            var basicAuthenticationHeader = context.Request.Headers["Authorization"]
                .FirstOrDefault(header => header.StartsWith("Basic", StringComparison.OrdinalIgnoreCase));
            var decodedHeader = new BasicAuthenticationHeaderValue(basicAuthenticationHeader);
            return decodedHeader;
        }
    }

    public class BasicAuthenticationOptions
    {
        public string Name { get; set; }

        public string Password { get; set; }

    }

    public class BasicAuthenticationHeaderValue
    {
        public BasicAuthenticationHeaderValue(string authenticationHeaderValue)
        {
            if (!string.IsNullOrWhiteSpace(authenticationHeaderValue))
            {
                this._authenticationHeaderValue = authenticationHeaderValue;
                if (TryDecodeHeaderValue())
                {
                    ReadAuthenticationHeaderValue();
                }
            }
        }

        private readonly string _authenticationHeaderValue;
        private string[] _splitDecodedCredentials;

        public bool IsValidBasicAuthenticationHeaderValue { get; private set; }
        public string UserName { get; private set; }
        public string Password { get; private set; }

        private bool TryDecodeHeaderValue()
        {
            const int headerSchemeLength = 6;
            if (this._authenticationHeaderValue.Length <= headerSchemeLength)
            {
                return false;
            }
            var encodedCredentials = this._authenticationHeaderValue.Substring(headerSchemeLength);
            try
            {
                var decodedCredentials = Convert.FromBase64String(encodedCredentials);
                this._splitDecodedCredentials = System.Text.Encoding.ASCII.GetString(decodedCredentials).Split(':');
                return true;
            }
            catch (FormatException)
            {
                return false;
            }
        }

        private void ReadAuthenticationHeaderValue()
        {
            IsValidBasicAuthenticationHeaderValue = this._splitDecodedCredentials.Length == 2
                                                   && !string.IsNullOrWhiteSpace(this._splitDecodedCredentials[0])
                                                   && !string.IsNullOrWhiteSpace(this._splitDecodedCredentials[1]);
            if (IsValidBasicAuthenticationHeaderValue)
            {
                UserName = this._splitDecodedCredentials[0];
                Password = this._splitDecodedCredentials[1];
            }
        }
    }
}


That’s it, we don’t have to make changes anywhere else to achieve the basic authentication in our web API project.

Now, we are all set up to make a secure API call using Basic authentication. Let’s try to execute the EmployeeController action method using Postman.

You have to configure the Basic authentication in your Postman application. Also, I have highlighted the options where you have to make changes.

Note:   If you are using Basic authentication. then it’s highly recommended to host your application in the HTTPS environment. Because username and password will be just converted to the base64 token. which can be tracked and decrypt easily.

Please let me know in the below comments section if you find this article useful.  Also, if you want me to update this article to validate the credential against a database or configuration. Let me know.

 

 

 

 

 

 

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on whatsapp
Share on email
Author Bio

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recommended for you
Connect With Us
Stay Connected

Subscribe to our newsletter today to receive updates on latest tech news, tutorials SEO tips many more.

Latest Articles

Free hub for guest blogging nerds and newbie writers

  • Submit Guest Post
  • Share your Knowledge
  • Build your Backlinks
  • Advertise your products
  • Make money by writing
Subscribe to our newsletter today to receive updates on latest tech news, tutorials SEO tips many more.