Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

csp-report endpoint in asp.net core

I'm trying to set up CSP in an asp.net core webapp, and the CSP part works fine, I can see the violations in the browser console as they are sent to the report-uri endpoint.

However, I cannot seem to create the correct method in a controller to receive these messages!

I create a method in the controller as:

[HttpPost]
[AllowAnonymous]
public IActionResult UriReport(CspReportRequest request)
{
    _log.LogError("CSP violation: " + request);
    return Ok();
}

and it will be called, but the 'request' parameter is always null. Some searching reveals that I need to use the [FromBody] attribute to read the data from the body, but once I put that in, it no longer gets called. (CspReportRequest is a class with properties matching the csp-report payload, but it doesn't work with string type either.)

So further reading suggests I add a handler for the 'application/csp-report' content-type that the body is being sent as:

services.Configure<MvcOptions>(options => {
    options.InputFormatters.OfType<JsonInputFormatter>().First().SupportedMediaTypes.Add(
        new MediaTypeHeaderValue("application/csp-report"));
});

But this doesn't seem to make a difference.

So - how do I make the correct controller signature, and/or the correct service handler options to receive the data.

like image 437
gbjbaanb Avatar asked Jul 22 '19 13:07

gbjbaanb


1 Answers

There are two things required to make this work. The first is adding [FromBody] to your CspReportRequest request parameter1:

public IActionResult UriReport([FromBody] CspReportRequest request)

Without [FromBody], the JsonInputFormatter will not be used to parse the request body. However, with [FromBody], you're going to start seeing 415 responses.

The second thing is configuring the JsonInputFormatter to support the application/csp-report media-type, which you've already attempted to do. The problem with your approach is that there are actually two instances of JsonInputFormatter configured, and you're affecting the wrong one. If you just change from First() to Last()2, it should work.

Why? The first JsonInputFormatter in the collection is actually an instance of JsonPatchInputFormatter, which extends JsonInputFormatter:

public class JsonPatchInputFormatter : JsonInputFormatter

This gets added first and so it's the one you're configuring. It can't process an instance of CspReportRequest because it has specific rules about handling JsonPatchDocument<T>, etc, so it passes on to the second JsonInputFormatter. This second instance isn't configured to support application/csp-report, as I've mentioned, so it also can't handle the request.


1 If you're using [ApiController], you won't need to use [FromBody], but everything from your question suggests that you're not using [ApiController].

2 Using Last() instead of First() isn't necessarily the best approach here, but it should demonstrate where the problem lies. There are many ways to get the specific JsonInputFormatter you are interested in.

like image 159
Kirk Larkin Avatar answered Nov 07 '22 23:11

Kirk Larkin