SwaggerBasicAuthMiddleware for securing swagger docs does not work with jwt authorize authentication

Tony 61 Reputation points
2023-02-23T21:23:50.2466667+00:00

Good day guys,

I have been trying to secure swagger docs using SwaggerBasicAuthMiddleware where it will authenticate the user before accessing the documentation and viewing of the methods. This part does work well. But the other part where i want to use jwt for accessing the methods and sending of post requests. Does not work having both. if i remove the SwaggerBasicAuthMiddleware for authentication of swagger ui. It starts to work with jwt and i can send request and get the token.

for example this is the secured part which works well.

User's image

But after accessing the the docs and methods. The authentication method to authorize the api with jwt does not work.

any help will be appreciated

thank you

Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | ASP.NET | ASP.NET API
{count} votes

Accepted answer
  1. Anonymous
    2023-02-28T07:53:49.06+00:00

    Hi @Tony

    According to your code, I create a sample with the following code, the Swagger authentication and JWT authentication works well.

    Program.cs

    using ApiWebApplication.Services;
    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;
    using Microsoft.OpenApi.Models;
    using System.Text;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = builder.Configuration["Jwt:Issuer"],
                ValidAudience = builder.Configuration["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
            };
        });
    builder.Services.AddSwaggerGen(c => {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Title = "JWTToken_Auth_API",
            Version = "v1"
        });
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
        {
            Name = "Authorization",
            Type = SecuritySchemeType.Http,
            Scheme = "Bearer",
            BearerFormat = "JWT",
            In = ParameterLocation.Header,
            Description = "Please enter a valid token",
        });
        c.AddSecurityRequirement(new OpenApiSecurityRequirement {
            {
                new OpenApiSecurityScheme {
                    Reference = new OpenApiReference {
                        Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                    }
                },
                new string[] {}
            }
        });
    });
    var app = builder.Build();
     
    app.UseAuthorization();
    
    app.UseSwaggerAuthorized(); 
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
    #if DEBUG
    
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "credit API v2");
        c.InjectStylesheet("/swagger-custom/swagger-custom-styles.css");
        c.InjectJavascript("/swagger-custom/swagger-custom-script.js", "text/javascript");
    #else
            
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "credit API v2");
            c.InjectStylesheet("/swagger-custom/swagger-custom-styles.css");
            c.InjectJavascript("/swagger-custom/swagger-custom-script.js", "text/javascript");
    #endif
    });
    
    app.UseHttpsRedirection(); 
    
    app.MapControllers(); 
    app.Run();
    
    

    SwaggerBasicAuthMiddleware class:

        public class SwaggerBasicAuthMiddleware
        {
            private readonly RequestDelegate next;
    
            public SwaggerBasicAuthMiddleware(RequestDelegate next)
            {
                this.next = next;
            }
    
            public async Task InvokeAsync(HttpContext context)
            {
                //Make sure we are hitting the swagger path, and not doing it locally as it just gets annoying :-)
                if (context.Request.Path.StartsWithSegments("/swagger"))
                {
                    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";
    
                    // Return unauthorized
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
                else
                {
                    await next.Invoke(context);
                }
            }
    
            public bool IsAuthorized(string username, string password)
            {
                // Check that username and password are correct
                return username.Equals("Admin", StringComparison.InvariantCultureIgnoreCase)
                        && password.Equals("a123");
            }  
        }
    

    SwaggerAuthorizeExtensions class:

        public static class SwaggerAuthorizeExtensions
        {
            public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<SwaggerBasicAuthMiddleware>();
            }
        }
    

    The login controller:

        [Route("api/[controller]")]
        [ApiController]
        public class LoginController : ControllerBase
        {
            private IConfiguration _config;
    
            public LoginController(IConfiguration config)
            {
                _config = config;
            }
            [AllowAnonymous]
            [HttpPost]
            public IActionResult Login([FromBody] LoginDTO login)
            {
                IActionResult response = Unauthorized();
                var user = AuthenticateUser(login);
    
                if (user != null)
                {
                    var tokenString = GenerateJSONWebToken(user);
                    response = Ok(new { token = tokenString });
                }
    
                return response;
            }
    
            [HttpPost]
            [Authorize]
            [Route("verify")]
            public ActionResult verifyaccount([FromBody] VerifyAccount Verify)
            {
                return Ok("Success");
            }
    
            private string GenerateJSONWebToken(LoginDTO userInfo)
            {
                var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
                var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    
                var token = new JwtSecurityToken(_config["Jwt:Issuer"],
                  _config["Jwt:Issuer"],
                  null,
                  expires: DateTime.Now.AddMinutes(120),
                  signingCredentials: credentials);
    
                return new JwtSecurityTokenHandler().WriteToken(token);
            }
    
            private LoginDTO AuthenticateUser(LoginDTO login)
            {
                LoginDTO user = null;
    
                //Validate the User Credentials    
                //Demo Purpose, I have Passed HardCoded User Information    
                if (login.Username == "admin")
                {
                    user = new LoginDTO { Username = "admin", EmailAddress = "******@gmail.com" };
                }
                return user;
            }
        }
    

    The result as below:

    image1


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.