Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core WebAPI Security Considerations

My WebAPI is, just that, an API backend for my UI to consume. In fact, I will have perhaps 10's of WebAPI services that my UI will use.

I'm having difficulty understanding what I need to consider in terms of security.

My APIs are secured using Bearer tokens, and allow https only. I have CORS set up and they only allow the origin https://my-front.end This all works great.

However.. how can I protect against C/XSRF and replay attacks on a WebAPI? Do I even need to?

Setting up anti-CSRF is rather painless with an ASP.NET MVC project, but how can you do it on a WebAPI one, from what I understand it relies on sending information, generated on the server, to the client to send along in the body of the request and through another channel (e.g. cookie or header). I read that you can protect against replay attacks by using a nonce (e.g. timestamp and random number) -- some how -- but can't find any implementation examples.

Is there anything else I need to consider?


Edit: front end uses vue.js, but we have a very competent JS programmer so any front-end implementations won't be a problem. It's just a matter of finding out what needs to be done!

May also be worth noting, for sake of obviousness, WebAPIs and FrontEnd run on different servers, so these are all, effectively, cross origin calls.

like image 706
Mardoxx Avatar asked May 17 '17 18:05

Mardoxx


1 Answers

OK so. First up, you will need to be sending the XSRF token in a header. To do this you need to go to your ConfigureServices method and setup the AntiForgery service to expect this header.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAntiforgery(x => x.HeaderName = "X-XSRF-TOKEN");
    services.AddMvc();
}

Next you need to generate the token. Because the front end and API are different services, you will need to work out when you do this. You could do it when you login for example, or you could have a dedicated endpoint doing this but the end result is the same.

You can either return the token value in a header or cookie it's up to you. In my example I've used a Cookie which I'll explain later but you can use a header if you like.

public class HomeController : Controller
{
    private readonly IAntiforgery _antiForgeryService;

    public HomeController(IAntiforgery antiForgeryService)
    {
        _antiForgeryService = antiForgeryService;
    }

    public IActionResult GetToken()
    {
        var token = _antiForgeryService.GetTokens(HttpContext).RequestToken;
        HttpContext.Response.Cookies.Append("XSRF-TOKEN", token, new CookieOptions { HttpOnly = false });
        return new StatusCodeResult(StatusCodes.Status200OK);
    }
}

The IAntiforgery service should already be able to be used (It's part of the "AddMVC" call you will be using already in .net core services).

OK, so now we have returned a cookie with a token value. Now we just need to be able to send it back.

Here is some jQuery doing the legwork

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.4/js.cookie.min.js"></script>
<script type="text/javascript">
    var token = Cookies.get("XSRF-TOKEN");

    $.ajax({
        url: "/",
        contentType: "application/json",
        type: "POST",
        headers: {
            "X-XSRF-TOKEN": token
        }
    });
</script>

Now something to note is that AngularJS automatically does this. When $http is used, it goes and looks for a cookie named "XSRF-TOKEN", and it will then send it as a header automatically. Because you are using Vue you will basically be doing this anyway but a bit more of a manual process.

Also important to note, DO NOT set this up to expect the cookie back as the CSRF token. Otherwise you've defeated the entire purpose of CSRF anyway.

Then you can go ahead and decorate your actions/controllers with the AntiForgery attribute.

[AutoValidateAntiforgeryToken]
public class HomeController : Controller
{

In conclusion what it basically boils down to :

  • Setup .net Core AntiForgery to expect a header value to use for the CSRF token
  • Have an endpoint that will manually generate a token for you to use and return it as a cookie/header
  • Have your front end read this value and store it for subsequent requests
  • On subsequent requests send the token value as a header (Not a cookie)

Mostly taken from here : http://dotnetcoretutorials.com/2017/05/18/csrf-tokens-angularjsjquery-asp-net-core/

like image 98
MindingData Avatar answered Sep 27 '22 16:09

MindingData