Skip to content

Cross Site Forgery Protection in Agent

KevM edited this page Nov 6, 2014 · 1 revision

Cross Site Request Forgery is type of attack which your web applicaiton should protect against.

CSRF is an attack which forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated. With a little help of social engineering (like sending a link via email/chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing.

Agent is using the Double Submit Cookies prevention technique in which a token is saved to both a cookie and as a parameter to the request being posted. The web application looks for these tokens and checks them against each other. If their values are missing or not matching the request is refused. This behavior is applied to all non GET endpoints exposed by the web application.

Page Load

The CSRF protection cookie is written during page load via the <requireScriptTag/> partial.

<script>
  define('appSettings', [], function() {
  return {
  approot :"${SiteResource('~/')}",
  apptoken: "${Agent.Core.Configuration.CacheBuster.Token}",
  maxRequestLength: "${Agent.Core.Configuration.UploadMaxRequestLength.Size}",
  enableLoginUI: ${Agent.Core.Configuration.FrontEndConfiguration.IsLoginUserInterfaceNeeded ? "true" : "false"},
  csrfToken: !{this.AntiForgeryFormToken().ToJSON()}
  }
  });
</script>

The this.AntiForgeryFormToken() is a page extension method provided by the Dovetail.SDK.Attachments bottle. It writes a cookie to the output of the page response and also returns a FormToken object.

public class FormToken
{
	public string Name { get; set; }
	public string TokenString { get; set; }
}

In the code above we are converting the object to JSON making the CSRF protection token available to Javascript. This token is then used during AJAX and regular Form POSTs to send a HTTP Header {Name}={TokenString} along with all AJAX requests.

AJAX

Agent sets up JQuery's AJAX support to send the CSRF token with the HTTP headers of all AJAX requests. This is done in app.js.

//CSRF HTTP headers to inject
var ajaxHeaders = {};
ajaxHeaders[appSettings.csrfToken.name] = appSettings.csrfToken.tokenString;

function setAjaxHeaders(xhr) {
  _.each(_.keys(ajaxHeaders), function (k) {
    xhr.setRequestHeader(k, ajaxHeaders[k]);
  });
}

$.ajaxSetup({
  cache: false,
  beforeSend: setAjaxHeaders
});

Regular Forms

When using a plain HTML <Form> element where no AJAX mechanism is used to POST the form, you will need to include the CSRF token somehow in the form. This is easy via Javascript.

$('#form').on('submit', function() {
  //add csrf input
  $form.append('<input type="hidden" name="' + appSettings.csrfToken.name + '" value="' + appSettings.csrfToken.tokenString + '"/>');
});