ASP.NET,C#.NET,VB.NET,JQuery,JavaScript,Gridview,SQL Server,Ajax,jQuery Plugins,jQuery UI,SSRS,XML,HTML,jQuery demos,code snippet examples.

Breaking News

  1. Home
  2. .NET CORE
  3. Anguler
  4. jQuery
  5. CSRF Tokens In AngularJS/jQuery With ASP.NET Core

CSRF Tokens In AngularJS/jQuery With ASP.NET Core

In a previous article we talked about using CSRF Tokens to protect against CSRF attacks. But their main usage was in using the Razor helpers to build a web application in ASP.net Core. But what if you are building a SPA using something like AngularJS? Your forms will no longer have access to the Razor helpers, but you still want to protect against CSRF exploits.
Luckily AngularJS actually has a handy “helper” that will add CSRF tokens as a header automatically as long as it can find a particular cookie. And in actual fact, even though Angular does most of the leg work for us and makes it easy, you can use any flavor of javascript frameworks using this pattern. At the end of the article we even show how you can get up and running using something as plain as jQuery. Let’s jump into it!

Anti Forgery Setup

Later on we will delve into how AngularJS works with CSRF Tokens, but for now what you need to know is that Angular will be sending the token in a header called “X-XSRF-TOKEN”. We need to let our API know this and expect it.
Inside your startup.cs inside your ConfigureServices method, you will need a call to “AddAntiforgery” and we will set the headername inside there.
public void ConfigureServices(IServiceCollection services)
{
 services.AddAntiforgery(x => x.HeaderName = "X-XSRF-TOKEN");
 services.AddMvc();
}

Setting The Cookie On The Initial Request

Now we need to return a cookie to our front end. There are 2 different ways to do this. You create an endpoint that does nothing more than return a response code of 200 and returns the cookie in the response, or you make it so when your index file is returned, the cookie is returned along with it.
Let’s go with the latter for now.
If you are returning your index file as a C# view, then you will need to inject the IAntiforgery service into your controller, generate a new token, and set it as a cookie. It looks like this :
public class HomeController : Controller
{
 private readonly IAntiforgery _antiForgeryService;

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

 public IActionResult Index()
 {
  var token = _antiForgeryService.GetTokens(HttpContext).RequestToken;
  HttpContext.Response.Cookies.Append("XSRF-TOKEN", token, new CookieOptions { HttpOnly = false });
  return View();
 }
}
Now importantly, the cookie name is XSRF-TOKEN and not X-XSRF-TOKEN. The cookie is missing the X on purpose (This catches people out!). And the other important thing is that HttpOnly is set to false on the cookie meaning that javascript is able to read the cookie. Generally speaking, if the cookie holds any sensitive info (Such as authentication cookies), you do not want to do this, but here it’s required.
If you are using a static index.html file that is not returned as a view. You will need to use middleware instead. In your startup.cs file you will have a method called “Configure”. On this method you need to add a parameter called IAntiforgery. Don’t worry too much about the order as this is all worked out using the servicecollection anyway. From there you will want to check if the user is requesting the root file (index.html) and if they are add a cookie onto the response.
Important! This middleware needs to come before the call to UseStaticFiles. The StaticFiles middleware short circuits the pipeline and returns the static file immediately meaning your cookie won’t be set.
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
 app.Use(next => context =>
 {
  string path = context.Request.Path.Value;
  if (
   string.Equals(path, "/") ||
   string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
  {
   var token = antiforgery.GetAndStoreTokens(context).RequestToken;
   context.Response.Cookies.Append("XSRF-TOKEN", token,new CookieOptions { HttpOnly = false });
  }

  return next(context);
 });

 app.UseStaticFiles();

 app.UseMvc(routes =>
 {
  routes.MapRoute(
   name: "default",
   template: "{controller=Home}/{action=Index}/{id?}");
 });
}

Setting The Cookie On Demand

A common scenario is going to be that the API and the front end are actually two seperate websites probably hosted on different boxes. With this in mind you won’t be serving any of the front end code from the API box, so you can’t set the cookie when the index.html file is requested.
In this scenario, you will need to setup an endpoint that will return the token for you. This could actually be after a user logs on, or it could be an endpoint that does nothing more than return a 200 and sets the cookie (Possibly with expiration). It will look something like this :
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 front end can call this endpoint at any point to generate a new CSRF token.

Using AngularJS

So what is there left to do in AngularJS? Well… actually nothing.
When $http is used inside Angular, it will now go ahead and look through your browser cookies for something named “XSRF-TOKEN”. If it finds it, it will then add a header to every request called “X-XSRF-TOKEN” to every request. You don’t have to set anything special up inside AngularJS… Phew.

Using jQuery

So jQuery isn’t going to be quite as easy as AngularJS, but the process will still be the same.
We are going to use the handy JS Cookie library that allows us to easily grab out values from Cookies from the front end. Then we are going to take that token and send it as a header with the name X-XSRF-TOKEN.
<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>

No comments