Basic Authentication in Swagger (Open API) .Net 5

Introduction

 
In this article we are going to learn about the how to setup the basic authentication for our API's 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
Packages used in this Project!
  1. 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.
 
 
Step 2
 
Add the Services Folder where we can add the business logic in that.
 
 
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 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5.   
  6. namespace BasicAuth.Services  
  7. {  
  8.     public class UserService : IUserService  
  9.     {  
  10.         public bool ValidateCredentials(string username, string password)  
  11.         {  
  12.             return username.Equals("admin") && password.Equals("Pa$$WoRd");  
  13.         }  
  14.     }  
  15. }  
I have added the interface for Dependency injection in controller level.
 
IUserService.cs  
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5.   
  6. namespace BasicAuth.Services  
  7. {  
  8.    public interface IUserService  
  9.     {  
  10.         bool ValidateCredentials(string username, string password);  
  11.     }  
  12. }  
Step 3
  
Add the Authenticate Handler code in order to handle the basic authentication.
 
 
BasicAuthenticationHandler.cs 
  1. using BasicAuth.Services;  
  2. using Microsoft.AspNetCore.Authentication;  
  3. using Microsoft.Extensions.Logging;  
  4. using Microsoft.Extensions.Options;  
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Linq;  
  8. using System.Net.Http.Headers;  
  9. using System.Security.Claims;  
  10. using System.Text;  
  11. using System.Text.Encodings.Web;  
  12. using System.Threading.Tasks;  
  13.   
  14. namespace BasicAuth.API  
  15. {  
  16.     public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>  
  17.     {  
  18.         #region Property  
  19.         readonly IUserService _userService;  
  20.         #endregion  
  21.  
  22.         #region Constructor  
  23.         public BasicAuthenticationHandler(IUserService userService,  
  24.             IOptionsMonitor<AuthenticationSchemeOptions> options,  
  25.             ILoggerFactory logger,  
  26.             UrlEncoder encoder,  
  27.             ISystemClock clock)  
  28.             : base(options, logger, encoder, clock)  
  29.         {  
  30.             _userService = userService;  
  31.         }  
  32.         #endregion  
  33.   
  34.         protected override async Task<AuthenticateResult> HandleAuthenticateAsync()  
  35.         {  
  36.             string username = null;  
  37.             try  
  38.             {  
  39.                 var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);  
  40.                 var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(authHeader.Parameter)).Split(':');  
  41.                 username = credentials.FirstOrDefault();  
  42.                 var password = credentials.LastOrDefault();  
  43.   
  44.                 if (!_userService.ValidateCredentials(username, password))  
  45.                     throw new ArgumentException("Invalid credentials");  
  46.             }  
  47.             catch (Exception ex)  
  48.             {  
  49.                 return AuthenticateResult.Fail($"Authentication failed: {ex.Message}");  
  50.             }  
  51.   
  52.             var claims = new[] {  
  53.                 new Claim(ClaimTypes.Name, username)  
  54.             };  
  55.             var identity = new ClaimsIdentity(claims, Scheme.Name);  
  56.             var principal = new ClaimsPrincipal(identity);  
  57.             var ticket = new AuthenticationTicket(principal, Scheme.Name);  
  58.   
  59.             return AuthenticateResult.Success(ticket);  
  60.         }  
  61.   
  62.     }  
  63. }  
 After adding the AuthenticationHandler code we can use the Authorize Attribute as 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
  1. using Microsoft.AspNetCore.Authorization;  
  2. using Microsoft.AspNetCore.Mvc;  
  3. using Microsoft.Extensions.Logging;  
  4. using System;  
  5. using System.Collections.Generic;  
  6. using System.Linq;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace BasicAuth.Controllers  
  10. {  
  11.     [Authorize]  
  12.     [ApiController]  
  13.     [Route("[controller]")]  
  14.     public class WeatherForecastController : ControllerBase  
  15.     {  
  16.         private static readonly string[] Summaries = new[]  
  17.         {  
  18.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"  
  19.         };  
  20.   
  21.         private readonly ILogger<WeatherForecastController> _logger;  
  22.   
  23.         public WeatherForecastController(ILogger<WeatherForecastController> logger)  
  24.         {  
  25.             _logger = logger;  
  26.         }  
  27.   
  28.         [HttpGet]  
  29.         public IEnumerable<WeatherForecast> Get()  
  30.         {  
  31.             var rng = new Random();  
  32.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast  
  33.             {  
  34.                 Date = DateTime.Now.AddDays(index),  
  35.                 TemperatureC = rng.Next(-20, 55),  
  36.                 Summary = Summaries[rng.Next(Summaries.Length)]  
  37.             })  
  38.             .ToArray();  
  39.         }  
  40.     }  
  41. }  
Step 4
 
I have setup this basic authentication in swagger so we have add the configuration of this swagger in startup.cs file.
 
Startup.cs
  1. using BasicAuth.API;  
  2. using BasicAuth.Services;  
  3. using Microsoft.AspNetCore.Authentication;  
  4. using Microsoft.AspNetCore.Builder;  
  5. using Microsoft.AspNetCore.Hosting;  
  6. using Microsoft.AspNetCore.HttpsPolicy;  
  7. using Microsoft.AspNetCore.Mvc;  
  8. using Microsoft.Extensions.Configuration;  
  9. using Microsoft.Extensions.DependencyInjection;  
  10. using Microsoft.Extensions.Hosting;  
  11. using Microsoft.Extensions.Logging;  
  12. using Microsoft.OpenApi.Models;  
  13. using System;  
  14. using System.Collections.Generic;  
  15. using System.Linq;  
  16. using System.Threading.Tasks;  
  17.   
  18. namespace BasicAuth  
  19. {  
  20.     public class Startup  
  21.     {  
  22.         public Startup(IConfiguration configuration)  
  23.         {  
  24.             Configuration = configuration;  
  25.         }  
  26.   
  27.         public IConfiguration Configuration { get; }  
  28.   
  29.         // This method gets called by the runtime. Use this method to add services to the container.  
  30.         public void ConfigureServices(IServiceCollection services)  
  31.         {  
  32.   
  33.             services.AddControllers();  
  34.  
  35.             #region Configure Swagger  
  36.             services.AddSwaggerGen(c =>  
  37.             {  
  38.                 c.SwaggerDoc("v1"new OpenApiInfo { Title = "BasicAuth", Version = "v1" });  
  39.                 c.AddSecurityDefinition("basic"new OpenApiSecurityScheme  
  40.                 {  
  41.                     Name = "Authorization",  
  42.                     Type = SecuritySchemeType.Http,  
  43.                     Scheme = "basic",  
  44.                     In = ParameterLocation.Header,  
  45.                     Description = "Basic Authorization header using the Bearer scheme."  
  46.                 });  
  47.                 c.AddSecurityRequirement(new OpenApiSecurityRequirement  
  48.                 {  
  49.                     {  
  50.                           new OpenApiSecurityScheme  
  51.                             {  
  52.                                 Reference = new OpenApiReference  
  53.                                 {  
  54.                                     Type = ReferenceType.SecurityScheme,  
  55.                                     Id = "basic"  
  56.                                 }  
  57.                             },  
  58.                             new string[] {}  
  59.                     }  
  60.                 });  
  61.             });  
  62.             #endregion  
  63.   
  64.             services.AddAuthentication("BasicAuthentication")  
  65.     .AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication"null);  
  66.   
  67.             services.AddScoped<IUserService, UserService>();  
  68.         }  
  69.   
  70.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  71.         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
  72.         {  
  73.             if (env.IsDevelopment())  
  74.             {  
  75.                 app.UseDeveloperExceptionPage();  
  76.                 app.UseSwagger();  
  77.                 app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json""BasicAuth v1"));  
  78.             }  
  79.   
  80.             app.UseHttpsRedirection();  
  81.   
  82.             app.UseRouting();  
  83.             app.UseAuthentication();  
  84.             app.UseAuthorization();  
  85.   
  86.             app.UseEndpoints(endpoints =>  
  87.             {  
  88.                 endpoints.MapControllers();  
  89.             });  
  90.         }  
  91.     }  
  92. }  
Step 5
 
Run the Application and by default swagger URL will be opened with default port. From the below image Authorize button is enabled and each API is unauthorized until your authorization is successfull.
 
 
 
Click on the Authorize Button. Pass the username and password to access the API.
 
 
 
Response from the API 
 
 
 
If you want to check with postman below is the process to access the API via Authorization.
 
 
In this article we learned that how can setup basic authentication for API via Swagger and Run and test it with Postman. If you want to clone the project 
 
URL : Github
 
Hope this article helps you  !!!
 
Keep learning.....!