.Net Core Web Api – Basic Authentication

For some of my pet projects, I would like to activate the basic authentication for protecting my web API services from unwanted accesses. .Net core allows us to register our middleware to be used as a pipeline in application scope so that we can inject our custom code for handling request before they go to our service. In the code listing below, I show you how to create a middleware and use it

1. Create basic authentication middleware

public class BasicAuthMiddleware
{
	private readonly RequestDelegate _next;
	private readonly string _realm;

	public BasicAuthMiddleware(RequestDelegate next, string realm)
	{
		_next = next;
		_realm = realm;
	}

	public async Task Invoke(HttpContext context)
	{
		string authHeader = context.Request.Headers["Authorization"];
		if (authHeader != null && authHeader.StartsWith("Basic "))
		{
			// Get the encoded username and password
			var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
			// Decode from Base64 to string
			var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
			// Split username and password
			var username = decodedUsernamePassword.Split(':', 2)[0];
			var password = decodedUsernamePassword.Split(':', 2)[1];
			// Check if login is correct
			if (IsAuthorized(username, password))
			{
				await _next.Invoke(context);
				return;
			}
		}
		// Return authentication type (causes browser to show login dialog)
		context.Response.Headers["WWW-Authenticate"] = "Basic";
		// Add realm if it is not null
		if (!string.IsNullOrWhiteSpace(_realm))
		{
			context.Response.Headers["WWW-Authenticate"] += $" realm=\"{_realm}\"";
		}
		// Return unauthorized
		context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
	}

	// Make your own implementation of this
	public bool IsAuthorized(string username, string password)
	{
		IConfiguration config = new ConfigurationBuilder()
			.AddJsonFile("appsettings.json", true, true)
			.Build();

		var basicAuthUserName = config["BasicAuth:UserName"];
		var basicAuthPassword = config["BasicAuth:Password"];
		// Check that username and password are correct
		return username.Equals(basicAuthUserName, StringComparison.InvariantCultureIgnoreCase)
			   && password.Equals(basicAuthPassword);
	}
}

The code does nothing else than reading out the HTTP request header and checks if Authorization is set. If there is any, then check if it is a Basic authentication. If it has the schema of Basic authentication, then decode the username and password with Base64 and check with the user name and password which saved in appsettings.json file.

The appsettings.json has following structure

{
  "ConnectionString": "Server=server_ip;Database=database_name;Uid=db_user_name;Pwd=db_user_password;SslMode=none",
  "BasicAuth": {
    "UserName": "user_name",
    "Password": "password"
  },
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

2. Use Basic authentication middleware

Just extend the Configure function with following codes

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

	app.UseMiddleware<BasicAuthMiddleware>("tetxua.com");

	app.UseMvc();
}

3. Postman

In Postman, you have to provide the basic authentication for access the REST api

Leave a Reply

Your email address will not be published. Required fields are marked *

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