0

I've got a web api that takes in a model

[CustomAuthorize]
public HttpResponseMessage UpdateStatus(Model model)

In the customAuthorize I have to read the contents of the request to validate it's not hacked

class CustomAuthorizeAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext context) 
    {
        var content = context.Request.Content.ReadAsFormDataAsync().Result;
    }
}

When I have the CustomAttribute applied to the web api, the model always comes back null. The binding doesn't happen. I've tried to use some cloning methods found here to clone the request and use that for the authorization but that doesn't seem to work either. How to clone a HttpRequestMessage when the original request has Content?

Does anyone know how I can retain the HttpContent in the request to let it bind to the method?

  • What are you trying to gain from reading the content in the AuthorizeAttribute? And what happens if you comment out this line? – matt_lethargic Nov 13 '18 at 16:40
  • @matt_lethargic a signature property is contained in the content and that signature is created by appending the values of all the other properties in the content and hashing them along with a secret string. To make sure the request isn't tampered with. I could just add a method in the api to validate it but I really really wanted to use the authorize attribute! –  Nov 13 '18 at 16:50

1 Answers1

1

This is because the content can only be read from a request once as the request is a forward-only stream. You're reading it in the attribute and then model binding is trying to read it again, but cannot.

This hackered article may help you understand

To be honest you might be better off using the Authorization header to put your hash in, this is after all what it's meant for. I've done this in the past using HMAC (check out this article). Reading the Authorization header in the Attribute can be done like this:

class CustomAuthorizeAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext context)
    {
        var authhash = context.Request.Headers.Authorization.Parameter;
    }
}

Also just for your information, there is an async version of the OnAuthorization method that you should use instead of adding .Result on the end of an async call, so your original code would look like:

class CustomAuthorizeAttribute : AuthorizationFilterAttribute
{
    public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        var content = await actionContext.Request.Content.ReadAsFormDataAsync(cancellationToken);
    }
}
matt_lethargic
  • 2,706
  • 1
  • 18
  • 33