Anti-Forgery Validation with ASP.NET Core MVC and Angular

This article shows how API requests from an Angular SPA inside an ASP.NET Core MVC application can be protected against XSRF by adding an anti-forgery cookie. This is required, if using Angular, when using cookies to persist the auth token.

Code: https://github.com/damienbod/AspNetCoreMvcAngular

Blogs in this Series

Cross Site Request Forgery

XSRF is an attack where a hacker makes malicious requests to a web app, when the user of the website is already authenticated. This can happen when a website uses cookies to persist the token of an trusted website, user. A pure SPA should not use cookies to as it is hard to protect against this. With a server side rendered application, like ASP.NET Core MVC, anti-forgery cookies can be used to protect against this, which makes it safer, when using cookies.

Angular automatically adds the X-XSRF-TOKEN HTTP Header with the anti-forgery cookie value for each request if the XSRF-TOKEN cookie is present. ASP.NET Core needs to know, that it must use this to validate the request. This can be added to the ConfigureServices method in the Startup class.

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

The XSRF-TOKEN cookie is added to the response of the HTTP request. The cookie is a secure cookie so this is only sent with HTTPS and not HTTP. All HTTP (Not HTTPS) requests will fail and return a 400 response. The cookie is created and added each time a new server url is called, but not for an API call.

app.Use(async (context, next) =>
{
	string path = context.Request.Path.Value;
	if (path != null && !path.ToLower().Contains("/api"))
	{
		// XSRF-TOKEN used by angular in the $http if provided
		var tokens = antiforgery.GetAndStoreTokens(context);
		context.Response.Cookies.Append("XSRF-TOKEN", 
		  tokens.RequestToken, new CookieOptions { 
		    HttpOnly = false, 
		    Secure = true 
		  }
		);
	}

	...

	await next();
});

The API uses the ValidateAntiForgeryToken attribute to check if the request contains the correct value for the XSRF-TOKEN cookie. If this is incorrect, or not sent, the request is rejected with a 400 response. The attribute is required when data is changed. HTTP GET requests should not require this attribute.

[HttpPut]
[ValidateAntiForgeryToken]
[Route("{id:int}")]
public IActionResult Update(int id, [FromBody]Thing thing)
{
	...

	return Ok(updatedThing);
}

You can check the cookies in the chrome browser.

Or in Firefox using Firebug (Cookies Tab).

Links:

https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery

http://www.fiyazhasan.me/angularjs-anti-forgery-with-asp-net-core/

http://www.dotnetcurry.com/aspnet/1343/aspnet-core-csrf-antiforgery-token

http://stackoverflow.com/questions/43312973/how-to-implement-x-xsrf-token-with-angular2-app-and-net-core-app/43313402

https://en.wikipedia.org/wiki/Cross-site_request_forgery

https://stormpath.com/blog/angular-xsrf

Advertisements

5 comments

  1. […] Anti-Forgery Validation with ASP.NET Core MVC and Angular (Damien Bowden) […]

  2. Mike · · Reply

    Hi Damien, thanks so much for this! I always thought the ‘Implicit Flow’ was the correct pattern for an Angular app accessing APIs from an MVC backend. Are you recommending that a Hybrid Flow is “better” / “more appropriate” in a setup exactly like yours? (ie. where an Angular SPA is inside an ASP.NET Core MVC application and presented as an MVC View). I guess I haven’t wrapped my head around ‘when’ to use the Hybrid Flow.

    1. Hi Mike, thanks,

      Implicit Flow is the correct flow for Angular apps accessing APIs. This is an MVC app with Angular in the view. Because it uses server rendered views, the extra protection can be added to protect against XSRF etc. I believe this setup to be protected.

      SPA Angular with API => Implicit Flow

      MVC with angular in the View => undecided which is better, must think about this and compare the safety concerns.

      Greetings Damien

  3. astegmaier · · Reply

    Can you help me understand more of the reasoning behind the statement “HTTP GET requests should not require this statement [i.e. the ValidateAntiForgeryToken attribute]”? If you’re talking about the GET endpoints that provide the MVC view that contains the Angular page, that makes sense to me (the token has to be provided at some point before it can be checked). But I’m confused about GET API calls–why wouldn’t you want to / need to validate the AntiForgeryToken on those?

    1. I was just refering that HTTP GET requests should not be changing data on the server, so that the GET request does not need to be validated. That’s all. But your also correct, if the GET returns sensitive data, the cookie should be validated.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: