0

I'm trying to implement CSRF using AntiForgeryToken from .Net Framework on a single page application. I've implemented some code inside my .csthml file and i've created an AuthorizeAttribute:

Index.cshtml

<script>

    @functions{
        public string GetAntiForgeryToken()
        {
            string cookieToken, formToken;
            System.Web.Helpers.AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }

    $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
        var xxx = '@GetAntiForgeryToken()';
        jqXHR.setRequestHeader("X-CSRF", xxx);
    });

</script>

ValidateHttpAntiForgeryTokenAttribute.cs

public class ValidateHttpAntiForgeryTokenAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        var headers = actionContext.Request.Headers;

        var headerToken = headers.Contains("X-CSRF") ? headers.GetValues("X-CSRF").FirstOrDefault() : null;

        if (headerToken == null)
        {
            return false;
        }

        var tokenValues = headerToken.Split(':');

        if (tokenValues.Length < 2)
        {
            return false;
        }
        else
        {
            var cookieToken = tokenValues[0];
            var formToken = tokenValues[1];
            try
            {
                AntiForgery.Validate(cookieToken, formToken);
            }
            catch(Exception ex)
            {
                return false;
            }
        }           
        return base.IsAuthorized(actionContext);
    }
}         

MyController.cs

    [HttpGet]
    [ValidateHttpAntiForgeryTokenAttribute]
    public HttpResponseMessage Get()
    {
     ...
    }

Every time that ValidateHttpAntiForgeryTokenAttribute is called, i got the following error:

The provided anti-forgery token was meant for user "CMP\usr", but the current user is "dev@company.net"

I would like to know why it displays the username of computer instead the username that is logged on application and why the token isn't changing when call GetAntiForgeryToken() is executed.

Thank in advance.

  • [Microsoft has provided implementation for AntiForgery Token validation](https://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute(v=vs.118).aspx) – Adnan Umer Aug 16 '16 at 15:14
  • That Microsoft implementation is only for HTML Form requests. The question here is about validating an XHR request. – Johann Nov 24 '20 at 15:12

1 Answers1

1

As quick fix (if you don't care about username validation inside anti-CSRF logic) would be:

AntiForgeryConfig.SuppressIdentityHeuristicChecks = true

somewhere in AppStart logic (global.asax).

serhiyb
  • 4,753
  • 2
  • 15
  • 24
  • Still the same problem –  Aug 16 '16 at 16:42
  • `AntiForgeryConfig` does not provide `SuppressIdentityHeuristicChecks` for me – DevEng Feb 21 '18 at 20:18
  • This does not prevent the exception in the question, which occurs during validation because the token contains a username which is different from the current Identity. `SuppressIdentityHeuristicChecks` simply makes Username, Claim, or AdditionalData required (https://github.com/mono/aspnetwebstack/blob/6248bfd24c/src/System.Web.WebPages/Helpers/AntiXsrf/TokenValidator.cs#L65), and throws an exception during token generation. Without it the username (if available) will still be set on the "form" token when generated, and validated on next request. – Johann Nov 24 '20 at 15:19
  • See updates to this answer: https://stackoverflow.com/a/15615786 – Johann Nov 30 '20 at 18:10