So i ‘m using two custom middlewares . One that validates the JWT Token on every request where it needs to be validated , and the one for the /admin routes . The problem is , even tho i specified the order in my Program.cs and the admin middleware is after the jwtTokenmiddleware , the admin one is executed first . Why is that ?
This is my code (relevant pieces): Program.cs
/* rest of the code*/
builder.Services.AddTransient<JwtTokenMiddlewareFactory>();
builder.Services.AddTransient<AdminMiddleware>();
/*
code
...
...
*/
app.UseMiddleware<JwtTokenMiddlewareFactory>();
app.UseMiddleware<AdminMiddleware>();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
/* end */
And these are my middlewares: The JWTTokenMiddleware:
using E_Commerce_BackEnd.Services.Helpers.AWS_Secret;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
namespace E_Commerce_BackEnd.MIddleware;
public class JwtTokenMiddlewareFactory : IMiddleware
{
private readonly ILogger<JwtTokenMiddlewareFactory> _logger;
private readonly ITokenService _tokenService;
public JwtTokenMiddlewareFactory(ILogger<JwtTokenMiddlewareFactory> logger, ITokenService tokenService)
{
_logger = logger;
_tokenService = tokenService;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
var endpoint = context.GetEndpoint();
// Check if the request path is for Google authentication and bypass JWT validation
var path = context.Request.Path;
if (path.StartsWithSegments("/signin-google") ||
path.StartsWithSegments("/google-response"))
{
await next(context);
return;
}
// Check if endpoint allows anonymous access
if (endpoint?.Metadata.GetMetadata<AllowAnonymousAttribute>() != null)
{
await next(context);
return;
}
if (context.Request.Cookies.TryGetValue("JWTToken", out var token) &&
context.Request.Cookies.TryGetValue("userLoggedIn", out var isLoggedIn))
{
var principalUser = await _tokenService.TokenValidation(token);
if (principalUser != null && isLoggedIn == "1")
{
context.User = principalUser;
_logger.LogInformation("User successfully set.");
}
else
{
_logger.LogWarning("Invalid JWT Token");
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Invalid JWT Token");
return;
}
}
else
{
_logger.LogWarning("Missing JWT Token");
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Missing JWT Token");
return;
}
await next(context);
}
catch (AuthenticationFailureException ex)
{
_logger.LogError(ex, "Authentication failure: Access was denied by the resource owner or by the remote server.");
context.Response.Redirect("http://localhost:8080/home");
}
}
}
and the Admin one :
namespace E_Commerce_BackEnd.MIddleware;
public class AdminMiddleware : IMiddleware
{
private readonly ILogger<AdminMiddleware> _logger;
public AdminMiddleware(ILogger<AdminMiddleware> logger)
{
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
_logger.LogInformation("Executin admin middleware");
var path = context.Request.Path;
_logger.LogInformation(path);
bool isLoggedInBool = context.Request.Cookies.TryGetValue("userLoggedIn", out var isLoggedInString);
if (path.StartsWithSegments("/admin"))
{
var isAdmin = false;
if (path.StartsWithSegments("/admin/login"))
{
_logger.LogInformation("Entering admin/login endpoint");
if (isLoggedInBool && isLoggedInString == "1" && context.Request.Cookies.TryGetValue("admin", out var adminLogInCheck))
{
if (adminLogInCheck == "1")
{
isAdmin = true;
await next(context);
return;
}
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
_logger.LogWarning($"Non-admin tried to acces -> {path}");
await context.Response.WriteAsync("You are not allowed here!");
}
}
if (isLoggedInBool && isLoggedInString == "1" && context.Request.Cookies.TryGetValue("admin", out var admin))
{
_logger.LogInformation("Entering /admin/* endpoint");
bool adminIsLoggedIn =
context.Request.Cookies.TryGetValue("adminLoggedIn", out var adminLoggedInString);
if (admin == "1" && adminIsLoggedIn && adminLoggedInString == "1" )
{
isAdmin = true;
await next(context);
return;
}
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
_logger.LogWarning($"Non-admin tried to acces/ Or invalid validation for the adminLoggedIn cookie -> {path}");
await context.Response.WriteAsync("You are not allowed here!");
return;
}
else
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
if (!isLoggedInBool)
{
_logger.LogWarning("User is not logged in (middleware)");
await context.Response.WriteAsync("User is not logged in");
return;
}else if (isLoggedInBool && !isAdmin)
{
_logger.LogWarning($"Admin cookie not present! Path that was tried -> {path}");
await context.Response.WriteAsync("Admin cookie not present");
return;
}
}
await next(context);
}
}
catch (Exception e)
{
_logger.LogError("Error in the admin middleware");
_logger.LogInformation(e.Message);
throw;
}
}
}
And when i try to log in normally as a Client , not admin , i get this logs
// rest of the logs above
// relevant ones only
info: E_Commerce_BackEnd.MIddleware.AdminMiddleware[0]
Executin admin middleware
info: E_Commerce_BackEnd.MIddleware.AdminMiddleware[0]
/api/user/login
The catch is , if i remove the admin middleware from the request pipeline , everything works perfectly , the Log in works , a JWT Token is assigned to the user , everything is good . But when i register and use the admin middleware , everything stops working ( no jwt token is assigned , nothing). What to do here ?