Basic Authentication in Swagger (Open API) .Net 5

Basic Authentication in Swagger (Open API) .Net 5

|Basic Auth - Swagger - .Net 5

In this article, we are going to learn about how to set up the basic authentication for our APIs using swagger in ASP.NET 5.0. As we all know, its newly launched Framework officially released in November. Here I am sharing the link to install the SDK for .Net 5

Github

Packages used in this Project!

Swashbuckle.AspNetCore (latest version)

The above package is installed by default if you are going with ASP.NET Core 5.0

Step 1

Create a Project in Visual Studio and make sure to go with the same process from the image shown below.

F1.png

Step 2

Add the Services Folder where we can add the business logic in that.

F2.png

For the time being, I have hardcoded the username and password in the code itself if you have the database with all the login credentials you can validate with that table.

UserService.cs

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  

namespace BasicAuth.Services  
{  
    public class UserService : IUserService  
    {  
        public bool ValidateCredentials(string username, string password)  
        {  
            return username.Equals("admin") && password.Equals("Pa$$WoRd");  
        }  
    }  
}

I have added the interface for Dependency injection at the controller level.

IUserService.cs

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  

namespace BasicAuth.Services  
{  
   public interface IUserService  
    {  
        bool ValidateCredentials(string username, string password);  
    }  
}

Step 3

Add the Authenticate Handler code in order to handle the basic authentication.

F3.png

BasicAuthenticationHandler.cs

using BasicAuth.Services;  
using Microsoft.AspNetCore.Authentication;  
using Microsoft.Extensions.Logging;  
using Microsoft.Extensions.Options;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Net.Http.Headers;  
using System.Security.Claims;  
using System.Text;  
using System.Text.Encodings.Web;  
using System.Threading.Tasks;  

namespace BasicAuth.API  
{  
    public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>  
    {  
        #region Property  
        readonly IUserService _userService;  
        #endregion  

        #region Constructor  
        public BasicAuthenticationHandler(IUserService userService,  
            IOptionsMonitor<AuthenticationSchemeOptions> options,  
            ILoggerFactory logger,  
            UrlEncoder encoder,  
            ISystemClock clock)  
            : base(options, logger, encoder, clock)  
        {  
            _userService = userService;  
        }  
        #endregion  

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()  
        {  
            string username = null;  
            try  
            {  
                var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);  
                var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(authHeader.Parameter)).Split(':');  
                username = credentials.FirstOrDefault();  
                var password = credentials.LastOrDefault();  

                if (!_userService.ValidateCredentials(username, password))  
                    throw new ArgumentException("Invalid credentials");  
            }  
            catch (Exception ex)  
            {  
                return AuthenticateResult.Fail($"Authentication failed: {ex.Message}");  
            }  

            var claims = new[] {  
                new Claim(ClaimTypes.Name, username)  
            };  
            var identity = new ClaimsIdentity(claims, Scheme.Name);  
            var principal = new ClaimsPrincipal(identity);  
            var ticket = new AuthenticationTicket(principal, Scheme.Name);  

            return AuthenticateResult.Success(ticket);  
        }  

    }  
}

After adding the AuthenticationHandler code we can use the Authorize Attribute as a header for each method in the controller to have this basic authentication setup. I have not added any other controller as I have reused the same controller.

WeatherForecastController.cs

using Microsoft.AspNetCore.Authorization;  
using Microsoft.AspNetCore.Mvc;  
using Microsoft.Extensions.Logging;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  

namespace BasicAuth.Controllers  
{  
    [Authorize]  
    [ApiController]  
    [Route("[controller]")]  
    public class WeatherForecastController : ControllerBase  
    {  
        private static readonly string[] Summaries = new[]  
        {  
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"  
        };  

        private readonly ILogger<WeatherForecastController> _logger;  

        public WeatherForecastController(ILogger<WeatherForecastController> logger)  
        {  
            _logger = logger;  
        }  

        [HttpGet]  
        public IEnumerable<WeatherForecast> Get()  
        {  
            var rng = new Random();  
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast  
            {  
                Date = DateTime.Now.AddDays(index),  
                TemperatureC = rng.Next(-20, 55),  
                Summary = Summaries[rng.Next(Summaries.Length)]  
            })  
            .ToArray();  
        }  
    }  
}

Step 4

I have set up this basic authentication in swagger so we have added the configuration of this swagger in a startup.cs file.

Startup.cs

using BasicAuth.API;  
using BasicAuth.Services;  
using Microsoft.AspNetCore.Authentication;  
using Microsoft.AspNetCore.Builder;  
using Microsoft.AspNetCore.Hosting;  
using Microsoft.AspNetCore.HttpsPolicy;  
using Microsoft.AspNetCore.Mvc;  
using Microsoft.Extensions.Configuration;  
using Microsoft.Extensions.DependencyInjection;  
using Microsoft.Extensions.Hosting;  
using Microsoft.Extensions.Logging;  
using Microsoft.OpenApi.Models;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Threading.Tasks;  

namespace BasicAuth  
{  
    public class Startup  
    {  
        public Startup(IConfiguration configuration)  
        {  
            Configuration = configuration;  
        }  

        public IConfiguration Configuration { get; }  

        // This method gets called by the runtime. Use this method to add services to the container.  
        public void ConfigureServices(IServiceCollection services)  
        {  

            services.AddControllers();  

            #region Configure Swagger  
            services.AddSwaggerGen(c =>  
            {  
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "BasicAuth", Version = "v1" });  
                c.AddSecurityDefinition("basic", new OpenApiSecurityScheme  
                {  
                    Name = "Authorization",  
                    Type = SecuritySchemeType.Http,  
                    Scheme = "basic",  
                    In = ParameterLocation.Header,  
                    Description = "Basic Authorization header using the Bearer scheme."  
                });  
                c.AddSecurityRequirement(new OpenApiSecurityRequirement  
                {  
                    {  
                          new OpenApiSecurityScheme  
                            {  
                                Reference = new OpenApiReference  
                                {  
                                    Type = ReferenceType.SecurityScheme,  
                                    Id = "basic"  
                                }  
                            },  
                            new string[] {}  
                    }  
                });  
            });  
            #endregion  

            services.AddAuthentication("BasicAuthentication")  
    .AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);  

            services.AddScoped<IUserService, UserService>();  
        }  

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
        {  
            if (env.IsDevelopment())  
            {  
                app.UseDeveloperExceptionPage();  
                app.UseSwagger();  
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "BasicAuth v1"));  
            }  

            app.UseHttpsRedirection();  

            app.UseRouting();  
            app.UseAuthentication();  
            app.UseAuthorization();  

            app.UseEndpoints(endpoints =>  
            {  
                endpoints.MapControllers();  
            });  
        }  
    }  
}

Step 5

Run the Application and by default swagger URL will be opened with the default port. From the below image Authorize button is enabled and each API is unauthorized until your authorization is successful.

F4.png

Click on the Authorize Button. Pass the username and password to access the API.

F5.png

Response from the API

F6.png

If you want to check with the postman below is the process to access the API via Authorization.

F7.png

In this article, we learned that how can set up basic authentication for API via Swagger and Run and test it with Postman. Please find the source code from here

Hope this article helps you !!!

Support me bmc-button.png

Keep learning…..!