0

I have wrote a Middleware which checks if Authorization Token is included in the header and based on that request are executed or returns error if token is missing. Now it is working fine for other Controllers. But What should I do for Login/Registration Controller which don't required Authorization headers. How can I configure my Middleware to ignore these.

Current Implementation of MiddleWare to Check Headers for Authorization Token.

public class AuthorizationHeaderValidator
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AuthorizationHeaderValidator> _logger;
    public AuthorizationHeaderValidator(RequestDelegate next, ILogger<AuthorizationHeaderValidator> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        StringValues authorizationHeader;
        Console.WriteLine(context.Request.Path.Value);
       if (context.Request.Headers.TryGetValue("Authorization", out authorizationHeader))
        {
            await _next(context);
        }
       else
        {
            _logger.LogError("Request Failed: Authorization Header missing!!!");
            context.Response.StatusCode = 403;
            var failureResponse = new FailureResponseModel()
            {
                Result = false,
                ResultDetails = "Authorization header not present in request",
                Uri = context.Request.Path.ToUriComponent().ToString(),
                Timestamp = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
                Error = new Error()
                {
                    Code = 108,
                    Description = "Authorization header not present in request",
                    Resolve = "Send Request with authorization header to avoid this error."
                }
            };
            string responseString = JsonConvert.SerializeObject(failureResponse);
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsync(responseString);
            return;

        }

    }
}
Shabir jan
  • 2,295
  • 2
  • 23
  • 37

3 Answers3

1

This is not a complete answer but only directions. Please post your code once you finish this task for next generations.

It seems you need a Filter and not Middlware as Middleware don't have access to rout data. Create new authorization filter by inheriting from Attribute and implementing IAuthorizationFilter or IAsyncAuthorizationFilter. There is only one method to implement

public void OnAuthorization(AuthorizationFilterContext context)
{
}

or

public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
}

Decorate controllers and/or actions that you want to exclude from this logic with AllowAnonymousAttribute. Inside your OnAuthorization method check if current action or controller has AllowAnonymousAttribute and if it is return without setting Result on AuthorizationFilterContext. Otherwise execute the logic from you original Middleware and set Result property. Setting Result will short-circuit the remainder of the filter pipeline. Then register your filter globally:

services.AddMvc(options =>
{
    options.Filters.Add(new CustomAuthorizeFilter());
});
Artur
  • 4,595
  • 25
  • 38
  • Helped me, thanks! I was trying to do this in middleware, not realizing the filters get executed after the middleware.. your answer pointed me in the right direction – Alex Dec 13 '19 at 13:52
  • @Alex can you post final solution? – Emanuele Apr 06 '22 at 09:55
0

Not sure why you need middleware to validate if the Authorization header is present. It's difficult to exclude the controllers this way as all requests will go through this middleware before they hit the MVC pipeline.

[Authorize] attribute will do the job for you, given that you have some form of authentication integrated. If you need to exclude the controllers which don't require authorization, you can simply add [AllowAnonymous] at the controller level or at the action method level. Please see the code snippet below from the Microsoft Docs

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
    }

    public ActionResult Logout()
    {
    }
}

If you must use a middleware, you can consider using it as an MVC filter, which means that it will be scoped to the MVC pipeline. For more details, please see this link. However, that will still not solve the problem to exclude the controllers without adding some convoluted logic, which can be quite complicated.

Shahzad Hassan
  • 993
  • 7
  • 14
0

I have solved my problem by Implementing PipeLine

public class AuthorizationMiddlewarePipeline
{
    public void Configure(IApplicationBuilder applicationBuilder)
    {
        applicationBuilder.UseMiddleware<AuthorizationHeaderValidator>();
    }
}

And than I am using it like this on either Controller Scope or Method scope

[MiddlewareFilter(typeof(AuthorizationMiddlewarePipeline))]
Shabir jan
  • 2,295
  • 2
  • 23
  • 37
  • 2
    I am glad you were able to solve the problem. If my suggestion of using Middleware as an MVC filter was helpful, please mark it as the accepted answer. Thanks – Shahzad Hassan Apr 18 '19 at 10:28