0

I have a .Net Core Web API with Custom Policy-Based Authorization (policies that check for claims and claims values on a JWT).

I need to log (to a database) every time a user call a Web API function, even when the authorization fail (especially on failures).

To do that I override these methods OnActionExecuting and OnResultExecuted (because i want to log every request on one filter, and, in other filter, the result of the request). But, if the Authorization fail, both filters never were trigged.

That's because the Authorization filter goes before the other filters (and if the request is unauthorized, short-circuit the pipeline).

So, when a user call a method without authorization I can't log it (i'm using Serilog to write a log file on the server, and works fine when authorization fail, but I want to log it to the database like when authorization is fine).

I try to write some filter before or after Authorization but I couldn't do it. May be i'm not thinking in the right way, and is more simple.

I read all this, but i couldn't figured out yet:

Thanks!

Community
  • 1
  • 1
Johna
  • 1,667
  • 1
  • 17
  • 27

2 Answers2

2

Have you tried the following options:

Using a global filter where you override the order, something like:

public void ConfigureServices(IServiceCollection services)
{

    services
        .AddMvc(options =>
            {
                options.Filters.Add(typeof(MyLoggingFilter), -2);
                options.Filters.Add(typeof(MyAuthFilter), -1);
            });
}

For attribute based filters you can implement IOrderedFilter

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
internal sealed class MyAuthorizationAttribute : Attribute, IAuthorizationFilter, IOrderedFilter
{
    public int Order => -2;
}

Inject a logger to the AuthFilter itself

public MyAuthFilter(ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger<MyAuthFilter>();
}
Fionn
  • 9,905
  • 10
  • 52
  • 79
  • I did not know that the filters order could be changed, thank you @Fionn, I'll try that (and inject the logger too) – Johna Jan 31 '17 at 13:43
  • The problem, is that I don't have my own "AuthFilter", i'm adding authorization as a services not in MVC options (services.AddAuthorization(options => {options.AddPoliciy(something using JWT claims)})), something like [this](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims) – Johna Jan 31 '17 at 14:26
  • I'm not all too familiar with the MVC claims authorization, but you can try to insert a Filter or Middleware before the builtin handlers run, – Fionn Jan 31 '17 at 20:15
  • Thanks @Fionn, that is, I created a Middleware and inserted it before de autentication – Johna Feb 01 '17 at 19:01
1

Sounds like you want to log higher in the .NET pipeline? You could take a look at the DelegatingHandler class rather than filters. These handlers are executed much higher in the pipeline, before your auth filters.

public class MyLogMessageHandler : DelegatingHandler
{
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {

      // Do logging with request or HttpContext.Current

    }
}

In your global.asax.cs (or equiv), u would then register the handler:

GlobalConfiguration.Configuration.MessageHandlers.Add(new MyLogMessageHandler());

Take a look at When to use HttpMessageHandler vs ActionFilter?

Also, we have an API logging and analytics solution that may helpful especially if you're on Azure since there is an Azure extension. https://www.moesif.com/features (full disclosure I am the CEO)

Community
  • 1
  • 1
Derrick
  • 1,014
  • 8
  • 8
  • Thank you @Derric, i'll try that (i'm not using Azure) – Johna Jan 31 '17 at 13:39
  • thank you again, that's what i want. I tried to use a DelegatingHanlder (the link your provide is very usefull!), then i realized that in .Net Core instead of HTTP hanlder is uses the [Middleware](https://docs.microsoft.com/en-us/aspnet/core/migration/http-modules). So i created a middleware like [this](http://blog.elmah.io/error-logging-middleware-in-aspnetcore/), and, i need to test more, but it's working :) – Johna Jan 31 '17 at 14:50