A single Razor view contains several forms, each with its own call to @Html.AntiForgeryToken()
<form id="f1">
@Html.AntiForgeryToken()
</form>
<form id="f2">
@Html.AntiForgeryToken()
</form>
As I understand it, both of these anti forgery tokens should be the same.
<form id="f1">
<input name="__RequestVerificationToken" type="hidden" value="duVT4VtiYybun-61lnSY1ol__qBwawnELooyqT5OSrCJrvcHvDs_Nr9GLxNxwvBaI4hUcKZVkm6mDEmH2UqNorHD1FnJbKJQLWe8Su_dhy_nnGGl5GhqqC3yRGzcxbBM0" />
</form>
<form id="f2">
<input name="__RequestVerificationToken" type="hidden" value="ZMISz3IWHU_HCKP4FppDQ5lvzoYhlQGhN1cmzKBPz4OgDzyqSUK3Q1dqvw1uHsb4eNyd9U3AbFcnW8tR7g1QS8Dyhp0tFc-ee1sfDAOqbLCcgd3PDnLCbXx09pnPREaq0" />
</form>
Why are the values different?
Surely they should be the same, because they are sent in the same Response from the server?
The documentation says nothing about calling it once only.
The Anti-Forgery token is not compared directly - the server has to unprotect it first and compare the protected data inside. Having different protected tokens doesn't necessarily mean they contain differing data.
What the
System.Web.Helpers.AntiXsrf.TokenValidator
compares is theSecurityToken
inside the decryptedAntiForgeryToken
instances. These instances, however, also contain anAdditionalData
field, aUserName
field and aClaimUid
field.Also, the
SecurityToken
inside theAntiForgeryToken
is directly copied from the (current if it is valid, else the freshly generated) AntiForgery cookie insideAntiForgeryWorker
.Given that all that data is serialized, encrypted then encoded, you may have variances in the protected token due to differences between the
AdditionalData
between tokens or it is likely due to a pseudorandom nonce used in the encryption process (which it likely uses, since I can test 2 completely different tokens as valid against the same cookie).I am afraid that won't work.
The antiforgery token also travels in the response cookie, so yours will contain just the last token, and therefore the first form will always fail.
You can try to do something like this:
I have tried it, and the same token is used in both forms.
These are not equal antiforgerytoken commands.
The MVC is generate uniqe for all uniqe commands.
So you shouldnt wait same generated ID. As I know :)
Thank you buffjape, for your comment
The values HAVE to be different. Not because of implementation inner workings or API voodoo but because each form represents an independent request to the server.
If the forms had the same token, once an attacker knew the token value for one form he would be able to trick the server into accepting the data sent by the other forms, although they were not submitted by the user, defeating the protection provided by the AntiCSRF Token.
The objective of the token is to provide a random id parameter, making it very hard for the attacker to fool the application into thinking that it was the logged in user that filled the form.
For those that are not acquainted with CSRF attacks, please take a look here.
The Response has nothing to do with it.
@Html.AntiForgeryToken()
is a static method ofHtmlHelper
which generates a unique token that is added to the html and the response cookie. Your calling the method multiple times so your generating multiple tokens.If it did not generate a unique token each time it would hardly be secure.
@Html.AntiForgeryToken() basically generate encrypted value based on the cookie and form data. So if you declare and use this @Html.AntiForgeryToken() for each than it will generate two different _RequestValidationToken. Better declare one global @token variable with @Html.AntiForgeryToken() method and it will create a single token for each request.