How to stop other websites from sending cross domain AJAX requests?

As well as via a cross-domain AJAX request with credentials, the POST in your example could also be sent by using a standard form without AJAX:

<form method="post" action="http://MyApp/Page" name="hiddenFormInIframe">

<input type="hidden" name="my" value="a" />

</form>
<script type="text/javascript">
  document.hiddenFormInIframe.submit();
</script>

This would also include cookies in the request.

The vulnerability you are talking about is called Cross Site Request Forgery.

You can guard against the POST being submitted from another domain by sending a header in your AJAX request and then checking the header server side. A common header to use is X-Requested-With. This header cannot be sent cross-domain via AJAX due to this header not being in the safe list (without CORS being enabled on your server). A HTML form cannot send this header either.

Only the following headers are allowed cross domain via AJAX:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type

The X-Requested-With header is automatically set when using JQuery and you can check for this in your ASP.NET code.

However in the past there have been some exploits via plugins such as Flash where headers could be set that were not possible via a browser (e.g. Referer) so to guard against this it is recommended to use the synchroniser token pattern which involves setting a token in a hidden field or in a header. This token will be validated as well as the authentication cookie for all requests with side-effects. That is, requests that change, submit or delete (normally POSTs).

For more info on CORS see here: http://www.html5rocks.com/en/tutorials/cors/


Cross-domain polices prevent domains from reading information in some circumstances from other domains that don't explicitly allow it with CORS headers. But, that doesn't prohibit cross-origin requests from going out. The request in your example should be hitting be a "pre-flight" OPTIONS request: A probing request to see whether the "actual" request will succeed.

Part of the solution may be to terminate OPTIONS requests early in the process: as soon as it can be determined whether the probing domain is allowed access.

A more complete solution may entail API access tokens. On each page-load, generate and embed an access token. Include that token in all API/AJAX requests. Any request that doesn't include the token should terminate early.


The best idea here is as other stated, use CSRF tokens. The most simplest form is to add the users IP adress as a identifier in a database, and then add a random value for this IP. The random value is the correct token.

For example, when someone visit your page to get the form, take the users IP, lets say: 12.12.12.12.

Add into a key-value database along with random value: 12.12.12.12 = ljghsdlghdlghdlshsdflgd (note, DONT use the example "ljghsdlghdlghdlshsdflgd", instead generate a pseudo-random value of a sufficent length)

Add this pseudo-random value as a hidden field.

On submit, use the users IP to look up the suggested reply. If the actual reply match the suggested reply, request is accepted. On ANY attempt to submit (regardless of successful or not), delete the record in database, if any exist. This means any CSRF attempts will invalidate the real tokens for the targeted user, and each token will be one-use only. Depending on what type of database it is, its either simple as setting the key to "", or simply delete it.

Like: 12.12.12.12 = "".

A good idea is also to expire these values by time, both for security, but also to get rid of unneccessary data in the database. Depending on if its a forum, it can be wise to have a couple of hours as a validty time, while if its a simple form to lets say, change a password, then its enough with about 5 minutes as validity time.


Another idea is captcha, which also prevents automated client-side attacks, like virus infections and automated remote Control trojans. Depending on sensitivity of the web application, it can be a good idea to use Captcha AND CSRF-tokens in unison. Do not follow the advice to use the same token for a whole session, its a bad idea security-wise since theres a small possibility that the user might be tricked into submitting a token to a attacker aswell to the site. A single-use token will be wortless to the attacker, but a multi-use token can be as dangerous as a session, which CSRF is designed to protect.

So use single-use tokens, its the best security compared to multi-use tokens, ans also single-use tokens does not need to be protected in transit as the CSRF article in one of the other replies suggest.