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:
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