1

In my form I have

@Html.AntiForgeryToken()

and the receiving controller action has

    [HttpPost, ValidateAntiForgeryToken]  
    public ActionResult Login(LoginViewModel model)  
    {
      //if detects a post request missing token, 
      //I wish to log form info for later inspection
    }

When a post request missing token occurs, the framework does not proceed into the method. If I wish to log form info for later inspection, what can I do and where?

  • I thought that `[ValidateAntiForgeryToken]` meant that it can only enter *with* a valid token, so it seems logical to me that it doesn't enter it when it doesn't have a token. – Daxtron2 May 25 '18 at 19:10
  • Sure. I wish to log form info for later inspection. What can I do? –  May 25 '18 at 19:11

3 Answers3

5

Another approach is to create a Custom Exception Filter to catch AntiForgery exceptions and log the form details from there, details below:

public class AntiForgeryExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        // ANTIFORGERY TOKEN NOT PRESENT
        if (!filterContext.ExceptionHandled && filterContext.Exception is HttpAntiForgeryException)
        {
            var request = new HttpRequestWrapper(System.Web.HttpContext.Current.Request);
            // Use your own logging service to log the results
            var _logger = new LoggingService();
            foreach (var key in request.Form.AllKeys)
            {
                var value = request.Form[key];
                // "key" is the form input name and "value" is the form input value
                _logger.Log("~~> " + key + " ==> " + value);
            }

            filterContext.ExceptionHandled = true;
        }
    }
}

and register the custom filter in global.asax:

protected void Application_Start()
{
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    GlobalFilters.Filters.Add(new AntiForgeryExceptionAttribute());
}
RickL
  • 3,318
  • 10
  • 38
  • 39
2
 [HttpPost]
 public async Task<IActionResult> Method(int id)
 {
        var formParameters = await Context.Request.ReadFormAsync();
        var requestVerification = formParameters["RequestVerificationToken"];
        string cookieToken = null;
        string formToken = null;

        if (!string.IsNullOrWhiteSpace(requestVerification))
        {
        var tokens = requestVerification.Split(':');

        if (tokens != null && tokens.Length == 2)
        {
            cookieToken = tokens[0];
            formToken = tokens[1];
        }


        var antiForgery = Context.RequestServices.GetService<AntiForgery>();
        try
        {
            antiForgery.Validate(Context, new AntiForgeryTokenSet(formToken, cookieToken))}
        catch
        {
           //log
        }
  }

This way you manually validate the anti forgery token, so you get the chance to let the method execute.

k1dev
  • 631
  • 5
  • 14
2

This may not be particularly useful to the original poster, but if you are in a .Net Core 2.2 or greater world, the anti-forgery token failure will not raise an exception but instead generate an AntiforgeryValidationFailedResult. So, you will instead want to create a filter on that result rather than on exceptions.

See this answer for more details and a code example.

Brandon Barkley
  • 720
  • 6
  • 21