I want to protect our login actions by AntiforgeryToken attribute - I know why the exception from the topic occurs, however I can't seem to find any good solution for it.
Let say we have the following situations:
It's 8:00 AM, application users are coming to work, they sit down and starting the login process - right now it is very possible that some of the users will get the same ValidationToken. After the first one logs in - all other will see the above exception (or some other custom exception screen) when they attempt to login.
Some user logged in, then accidentally pressed the "back" button and attempted to log in again - while this is more unlikely, it can happen, and I don't want users to see exceptions when it does.
So the question is simple - how to prevent the above situations, or how to handle them so that users won't notice anything. I have tried the following:
- Setting the AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start in Global.asax - it didn't fix the problem, I still get the same exception
- Setting the [OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")] on the method with [ValidateAntiForgeryToken] attribute - again, no luck there
Right now I was thinking to manually validate the token in action body, catch the error, and check if attempt was made by anonymous user:
public ActionResult SomeAction()
{
try
{
AntiForgery.Validate();
}
catch(HttpAntiForgeryException ex)
{
if(String.IsNullOrEmpty(HttpContext.User.Identity.Name))
{
throw;
}
}
//Rest of action body here
//..
//..
}
The above seems to prevent the errors - but is it safe? What alternatives are there?
Thanks in advance.
Best regards.
EDIT:
The final "solution" was to disable token validation on login form - there may be a better way to handle it, but it seems that all solutions I found, were ugly workarounds similar to mine proposed above.
Since there is no way to know how "safe" those alternatives are (if they are safe at all), we decided to do disable token validation on login.
Try setting (in global.cs):
This will add the name identifier to your token,
As for the double login issue try to use a script to document the date and time of the original submit to stop a second submit with the same token.
So we know one thing; users like the back button and have a habit of the double click, this is a big issue with AntiforgeryToken.
But depending on what your application does there are ways to limit their compulsion to do so. The simplest of which is to do your best to try and make the visitor not feel like they need to “rewind” their request to alter it.
“What’s going on?” - Keeping the user informed
When a AntiForgeryToken doesn’t validate your website will throw an Exception of type System.Web.Mvc.HttpAntiForgeryException.
If you’ve set up correctly you’ve got friendly errors turned on and this will mean your error page will not show an Exception and show a nice error page that tells them what is up.
You can make this a little easier by at least giving the user a more informative page targeted at these exceptions by catching the HttpAntiForgeryException.
and your
/error/antiforgery
view can tell them Sorry you have tried to submit the same information twiceAnother Idea is to log the error and return the user to the login screen:
Create a
HandleAntiforgeryTokenErrorAttribute
class that Overrides the OnException method.HandleAntiforgeryTokenErrorAttribute.cs:
Global Filter:
I would also use a few tools to record all your information as login is critical part of your application
NLog for general logging and emails on critical application exceptions (including web exceptions).
Elmah for filtering and email of web exceptions.
EDIT: Also you may want to look at a jQuery plugin called SafeForm. Link
EDIT:
I have seen allot of debate on this and everyone's views on the subject have valid points, How i look at it is (Taken from owasp.org)
Now i also use authorized IP addresses for login to allot of my applications with 2 factor authorization if the users IP address changes, so if Cross-Site Request Forgery was in play the user wouldn't match the IP address and request 2 factor authorization. almost like the way a security router would work. but if you want to keep it on your login page i don't see a problem as long as you have your friendly error pages set up people will not get upset as they will see they did something wrong.