CSRF protection is what you should do to do just that, protect against cross-site request forgery.
A quick overview of CSRF :
Cross-site request forgery (CSRF) is an attack that forces the end user to perform unwanted actions in the web application in which they are currently authenticated. CSRF attacks are specifically designed for stateful requests, not data theft, because the attacker is not able to see the response to a fake request. With a little help in social engineering (for example, when sending a link by email or chat), an attacker can trick users of a web application into taking actions to select an attacker.
The following is an example of a CSRF attack against your web API if it is not protected:
<form action="http://yourapi.com/api/DeleteAccount"> <input type="text" name="id" /> <input type="submit" /> </form>
By submitting this form from a hacked website, if you are logged into your web API using cookie authentication (as an example) as an administrator account, it can delete accounts from your system.
This is because when you are redirected to your API, your browser goes through a cookie, which is stored in the yourapi.com domain, thus authenticating the user and performing the required actions. This attack vector is different from using, for example, a token carrier to authenticate with your API, because the third party does not know this token.
As you correctly stated and implemented, the use of an anti-fake token can protect against this as a generated token sent to the client in a web response and then sent back by the client and confirmed to ensure that this is a permitted request from somewhere we expect. As a token-holder, a third-party organization may not know the token that you sent in your request from the server. In this regard, what you implemented is absolutely true, and passing the token to the client is how we expect it to work.
In ASP.NET MVC (sans API), this is implemented as follows:
<form .. /> @Html.AntiForgeryToken() </form>
.. and verified server side with:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Action(MyModel model) {
When you call @Html.AntiForgeryToken() , this method sets a cookie (containing a cookie token) and sends it to the client, and also generates a <input type="hidden" ..> to send to the client. Then they are sent back and checked on the server side.
Armed with this knowledge, you can see that your concern about sending a “cookie token” and a “form token” is unfounded, as this is what happens anyway.
I see your cause for concern, but what you are trying to mitigate seems to be a Man in the Middle (MitM) attack, not a CSRF. To get around a significant portion of MitM attacks, you need to make sure your site / API works through HTTPS. If your client is still vulnerable to a MitM attack, your API is likely to be of the least value to the attacker.