Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override anti-forgery token errors on login page

I have a site that receives a large amount of the following errors:

The provided anti-forgery token was meant for a different claims-based user than the current user.

The anti-forgery cookie token and form field token do not match.

I would like to prevent the site from throwing an error if the anti-forgery token is meant for no user but contains a user on the login page, for example:

The provided anti-forgery token was meant for user "", but the current user is "Garret".

I don't want this exception to apply to any other page other than the login page. So I don't want to add AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; to the entire site. I also want to keep the site as secure as possible since it contains HIPAA data. What can I do to keep it as secure as possible but still try to prevent this error on the login page because it is making it difficult for users to use?

The site is hosted on load balancing servers but I don't think this is the issue. I think the error is mostly caused by using the browser's back button, having the login page opened for a while before logging in, already being logged in or pressing login more than once. Also some users access it through an application that may not be loading the page and just trying to post the login information.

So please let me know what the best option is to prevent this error on the login page while still being as secure as possible?

like image 753
Garrett Fogerlie Avatar asked May 27 '16 07:05

Garrett Fogerlie


People also ask

How do I disable AntiForgeryToken?

Anti-forgery token validation is enabled by default in Razor Pages. You can disable validation either globally or on individual pages by using [IgnoreAntiforgeryToken] . You can prevent forms from creating anti-forgery tokens by using asp-antiforgery="false" in the form tag helper.

How do you fix Anti-forgery cookies?

Try quick fixes The common “possible solutions” to anti-forgery token/cookie related issues are disabling output caching and enabling heuristic checks.

Where are anti-forgery tokens stored?

ASP.NET Core uses a hidden field to store the anti-forgery token and uses the ValidateAntiForgeryToken attribute to validate the token. As the token is sent to the browser in a hidden field, it is also stored in an HttpOnly cookie.

What is an anti-forgery token?

Anti-Forgery TokensOne token is sent as a cookie. The other is placed in a hidden form field. The tokens are generated randomly so that an adversary cannot guess the values. When the client submits the form, it must send both tokens back to the server.


2 Answers

What I ended up doing, and it seems to be working while still providing the same security, is to manually check the antiforgery token after checking if the user is logged in.

    [HttpPost]
    [AllowAnonymous]
    //[ValidateAntiForgeryToken]
    [OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        // Skip the login process if the user is already logged in
        if (User.Identity.IsAuthenticated) 
        {
            return RedirectToAction("Index", "Home");
        }
        // Check the anti forgery token now
        System.Web.Helpers.AntiForgery.Validate();
        ...
like image 179
Garrett Fogerlie Avatar answered Oct 15 '22 09:10

Garrett Fogerlie


There is an answer for concurrent login attempts originated from certain user:

How can I fix anti-forgery token was meant for user "", but the current user is "xxxx " error

If AntiForgeryToken exception comes when the user has too long time to fill in login page, simply redirect to that page and show a message explaining his/her session (i.e. security token) had expired.

[HttpPost]
[ValidateAntiForgeryToken]
[HandleError(View="Login", ExceptionType = typeof(HttpAntiForgeryException))]
public ActionResult Login(LoginModel model)
{
     // some login processing stuff
}

If the exception comes from user's clicking back button, provide JS function on client-side which prevent the back button action on login page only:

<body onload="window.history.forward()">...</body>

// or wrap it inside a function
<script type="text/javascript">
function noBackOnLogin() {
        window.history.forward();
        history.pushState(null, document.title, url); // if you want to include Mobile Safari, see https://stackoverflow.com/a/34337617/6378815
    }
</script>
<body onload="noBackOnLogin();" onpageshow="if (event.persisted) noBackOnLogin();">...</body>

For another case that certain user has already logged in, redirect to the index or somewhat page indicating their user name (with User.Identity.Name).

I hope this explanation useful.

like image 42
Tetsuya Yamamoto Avatar answered Oct 15 '22 10:10

Tetsuya Yamamoto