20

I have implemented antiforgery token on my login page.

Now I had one user pressing back key on the keyboard, and when they click on login button again after filling their credentials, they get error page.

Is there some better way of handeling this case like redirect them to fresh login page?

Page that is login page is :/account/logon

If login details are sucessfull the user is redirected to :Home/Index page on which the user pressed button back.

cpoDesign
  • 8,953
  • 13
  • 62
  • 106

4 Answers4

23

Don't implement the ASP.NET AntiForgeryToken on your login page. The token is based on a username among other criteria and a login page assume the attacker already has credentials to a system in order to be able to exploit csrf on that page.

However, you should use some form of CSRF protection on your login page - see https://security.stackexchange.com/a/2126/51772

Community
  • 1
  • 1
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • I don't understand your answer completely. Why is it wrong by using the token on the login page, since without it it's possible to do a csrf attack on the LogOn function? – Marthijn Feb 24 '12 at 18:00
  • 1
    CSRF functions 'usually' proxy a request through an authenticated user to do some action on behalf of that user. If an attacker is attacking a login page, that means they already have credentials. In that case they could login themselves. If it is an internal app and they are proxying from the outside, then they could just wait until a user logs in. If you want to use a token here, you'll have to hack the existing method and come up with something new. The antiforgery token is specific to 'who is logged on'. So once you login, then go back, the old token is no longer valid, hence your problem. – Adam Tuliper Feb 24 '12 at 19:40
  • Most people don't do this on a login page. If you are extra cautious and think someone could actually use credentials to proxy a request to login, the you will have to force your pages to not cache and load up new tokens each time, or come up with your own custom scheme as the built in antiforgery token won't work in this case. – Adam Tuliper Feb 24 '12 at 19:40
  • Thanks for the explanation, but what if someone is brute forcing your logon page from an external app? Doesn't protect an AF token you in that case, or do you need to check the ref url? – Marthijn Feb 26 '12 at 09:35
  • Then an account lockout policy stops them easily. Referer can be forged. – Adam Tuliper Feb 26 '12 at 16:41
  • @AdamTuliper: how ever if you are up to steal credentials, its not much that will stop you. But its making it more difficult for the attacker and using it with additional security check, such as captcha and max login attempts, i believe that its better solution to have it in there after all. – cpoDesign Apr 05 '12 at 07:31
  • By putting this on the login page you are hacking around it to get it to work, it's non standard, the next dev will look at the code and say 'whats up with this hack?', and it provides you with an unbelievable small increase. If they have your credentials, they simply go and login to your application. If its an internal application they simply find a site they visit and use XSS to exploit that to redirect to the original. This truly gives you virtually nothing. Plus - when was the last time you saw a captcha on a simple login page? Again, a reason why you wouldn't. And yes, I agree on the max – Adam Tuliper Apr 05 '12 at 13:47
  • logins, I go into this and quite a few security subjects in detail in my security course if you are interested (its 5 hours of this) http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=hack-proofing-dotnet-app – Adam Tuliper Apr 05 '12 at 13:48
  • 15
    i was quite convinced with @AdamTuliper reply till i stumbled upon this - http://security.stackexchange.com/questions/2120/when-the-use-of-a-antiforgerytoken-is-not-required-needed There is a reference to this paper - http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf - which is quite a good read – aunlead Nov 02 '12 at 11:18
  • 2
    I should've prefaced my answer with 'in asp.net mvcs implementation of the anti forgery token' as it is based on login name. A token from an anonymous user may not provide the needed protection- ill have to test as its tied to the login name in most cases if I recall. – Adam Tuliper Nov 04 '12 at 09:40
  • 1
    Tokens ARE needed on sign up and sign in pages: http://security.stackexchange.com/questions/2120/when-the-use-of-a-antiforgerytoken-is-not-required-needed – Richard Nov 19 '14 at 10:16
  • 4
    Danger - Do **not** do this! @aix is correct, this answer introduces a security vulnerability where a CSRF request could be used is to force a login against credentials the attacker controls. The attacker could then use the same account to view the user's activity on the site. See http://en.wikipedia.org/wiki/Cross-site_request_forgery#Forging_login_requests and http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf Please consider rescinding or editing this answer, as it is very dangerous advice. – ShadowChaser Apr 12 '15 at 16:18
  • 1
    @ShadowChaser His comment made it clear that he's specifically talking about how it's implemented in ASP.NET MVC 5. – Justin Skiles Aug 07 '15 at 15:43
  • 6
    So if we shouldn't use the ASP.NET AntiForgeryToken on the login page and a form of CSRF protection is required, what is a good alternative? I mean is there a good library or something you recommend? – nmit026 Jan 03 '17 at 00:44
  • @nmit026 I'm not sure how it's implemented in ASP.NET, but in ASP.NET Core it is definitely a good solution against a login CSRF attack. It doesn't matter that it's based on a username, the security is still there. This tutorial shows you exactly how AF tokens can protect against a login CSRF attack: https://levelup.gitconnected.com/antiforgery-tokens-behind-the-scenes-dcddda54db8a – David Klempfner Jan 18 '21 at 09:29
7

I've written up a full solution here: https://richardcooke.info/en/2014/keep-users-signed-in-after-asp-net-deploy/

Here's the necessary code to call in your controller form your GET method:

private void SetANewRequestVerificationTokenManuallyInCookieAndOnTheForm()
{
    if (Response == null)
        return;

    string cookieToken, formToken;
    AntiForgery.GetTokens(null, out cookieToken, out formToken); 
    SetCookie("__RequestVerificationToken", cookieToken);
    ViewBag.FormToken = formToken;
}

private void SetCookie(string name, string value)
{
   if (Response.Cookies.AllKeys.Contains(name))
       Response.Cookies[name].Value = value;
   else
       Response.Cookies.Add(new HttpCookie(name, value));
}

and code to put in your view in place of Html.AntiForgeryToken():

@if (ViewBag.FormToken != null)
{
    <text><input name="__RequestVerificationToken" type="hidden" value="@ViewBag.FormToken" /></text>
}
else
{
    <text>@Html.AntiForgeryToken()</text>
}
Richard
  • 14,798
  • 21
  • 70
  • 103
5

My solution to this was:

Reload a page if it hits login page again. this will ensure fresh loading of antiforgery token

and all is done

cpoDesign
  • 8,953
  • 13
  • 62
  • 106
  • 1
    I'm using the same approach. To do it I made sure the cache headers were set correctly: (Cache-Control=no-cache, no-store, must-revalidate), (Expires=-1). Considering that the antiforgery tokens are "dynamic" depending on the user context, it doesn't leave much option other than to set no-cache on all application pages (sigh), right? I mean, a user can login and then potentially click back to an arbitrary app page they were previously on...and if that page is cached and they try to post from it then they'll hit an error. Seems to me that no-cache for the entire web app is the only solution :( – sammy34 Feb 06 '15 at 21:07
  • Note: the up-voted answer of "don't implement a forgery token" doesn't cover the case where a user logs in and then navigates back to some other (non-login) application page where a forgery token IS sensible to have. – sammy34 Feb 06 '15 at 21:08
1

Instead of checking User.Identity.IsAuthenticated like some other posts mentioned I used a custom attribute to handle the exceptions and redirect the user to the home page if it is a HttpAntiForgeryToken

I believe this avoids any potential security concerns of using the other methods, and that [ValidateAntiForgeryToken] should always be used on POST methods

public override void OnException(ExceptionContext filterContext)
    {
        var controllerName = (string)filterContext.RouteData.Values["controller"];
        var actionName = (string)filterContext.RouteData.Values["action"];
        var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
        if (filterContext.Exception is HttpAntiForgeryException)
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "action", "Index" },
                    { "controller", "Home" }
                });

            filterContext.ExceptionHandled = true;
        }
}
bla9x
  • 469
  • 7
  • 17
  • Protected Overrides Sub OnException(filterContext As ExceptionContext) If TypeOf filterContext.Exception Is HttpAntiForgeryException Then Dim result = New RouteValueDictionary() filterContext.Result = RedirectToAction("LogOn", "Account") filterContext.ExceptionHandled = True End If End Sub – AHMED RABEE Feb 01 '20 at 06:02