16

I have the following in my BasePage class which all my ASPX pages derive from:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    ViewStateUserKey = Session.SessionID;
}

I also have a machineKey set in Web.config. I don't think this error is because of a web farm because this happens on my dev machine too.

My host has now upgraded to .NET 3.5 SP1. After this update, everytime I compile with the ViewStateUserKey setting above, I constantly get the "Validation of viewstate MAC failed" error on every postback.

What am I doing wrong here? Is this setting even necessary anymore with the latest framework update?

Druid
  • 6,423
  • 4
  • 41
  • 56

5 Answers5

18

OK - Im a year late to the conversation - but how is this the correct answer? This applies only in the case of authenticated users and using the ViewStateUserKey as the username is a lot easier to guess than a session id GUID.

BTW if you want to 'fix' the code up top, use the Session ID, however you must set a session variable in order for the session id to stop from changing every time. Ex. Session["Anything"] = DateTime.Now

ViewStateUserKey = Session.SessionID;

This of course is assuming you are going to use sessions, otherwise you need some other key to use such as the username or any other guid kept in a cookie.

Druid
  • 6,423
  • 4
  • 41
  • 56
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • 1
    An added note, sometimes I see the sessionid change every time until the session is used, and other times the session cookie is sent to the client right away without seemingly using the session. I'm not 100% sure why yet on this but just something I've noticed. – Adam Tuliper Jan 19 '12 at 16:43
  • This was very helpful. I didn't know that ASP doesn't keep session if nothing saved in the it. – Reza Aug 20 '13 at 19:31
9

I've searched around quite a bit to find the definitive cause of the issue. This post from Microsoft really helped explain all the different causes. http://support.microsoft.com/kb/2915218 Cause 4 is what we have landed on which is an invalid ViewStateUserKeyValue

Setting ViewStateUserKey to Session.SessionID or User.Identity.Name did not work for us.

We intermittently got the validation error due to the following. When the application pool is reset by IIS, the session is renewed in effect causing the error. We drop the Session on login to avoid session fixation, also resulting in the error on login.

What finally worked for us was a cookie based solution, which is now provided in VS2012.

public partial class SiteMaster : MasterPage
{
    private const string AntiXsrfTokenKey = "__AntiXsrfToken";
    private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
    private string _antiXsrfTokenValue;

    protected void Page_Init(object sender, EventArgs e)
    {
        //First, check for the existence of the Anti-XSS cookie
        var requestCookie = Request.Cookies[AntiXsrfTokenKey];
        Guid requestCookieGuidValue;

        //If the CSRF cookie is found, parse the token from the cookie.
        //Then, set the global page variable and view state user
        //key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad
        //method.
        if (requestCookie != null
        && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
        {
            //Set the global token variable so the cookie value can be
            //validated against the value in the view state form field in
            //the Page.PreLoad method.
            _antiXsrfTokenValue = requestCookie.Value;

            //Set the view state user key, which will be validated by the
            //framework during each request
            Page.ViewStateUserKey = _antiXsrfTokenValue;
        }
        //If the CSRF cookie is not found, then this is a new session.
        else
        {
            //Generate a new Anti-XSRF token
            _antiXsrfTokenValue = Guid.NewGuid().ToString("N");

            //Set the view state user key, which will be validated by the
            //framework during each request
            Page.ViewStateUserKey = _antiXsrfTokenValue;

            //Create the non-persistent CSRF cookie
            var responseCookie = new HttpCookie(AntiXsrfTokenKey)
            {
                //Set the HttpOnly property to prevent the cookie from
                //being accessed by client side script
                HttpOnly = true,

                //Add the Anti-XSRF token to the cookie value
                Value = _antiXsrfTokenValue
            };

            //If we are using SSL, the cookie should be set to secure to
            //prevent it from being sent over HTTP connections
            if (FormsAuthentication.RequireSSL &&
            Request.IsSecureConnection)
            responseCookie.Secure = true;

            //Add the CSRF cookie to the response
            Response.Cookies.Set(responseCookie);
        }

            Page.PreLoad += master_Page_PreLoad;
        }

        protected void master_Page_PreLoad(object sender, EventArgs e)
        {
            //During the initial page load, add the Anti-XSRF token and user
            //name to the ViewState
            if (!IsPostBack)
            {
                //Set Anti-XSRF token
                ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;

                //If a user name is assigned, set the user name
                ViewState[AntiXsrfUserNameKey] =
                Context.User.Identity.Name ?? String.Empty;
            }
            //During all subsequent post backs to the page, the token value from
            //the cookie should be validated against the token in the view state
            //form field. Additionally user name should be compared to the
            //authenticated users name
            else
            {
                //Validate the Anti-XSRF token
                if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                || (string)ViewState[AntiXsrfUserNameKey] !=
                (Context.User.Identity.Name ?? String.Empty))
            {
            throw new InvalidOperationException("Validation of
            Anti-XSRF token failed.");
            }
        }
    }
}

Source

Vincejtl
  • 169
  • 1
  • 6
  • Could You please, elaborate more? Not only *links*. – Kamiccolo Apr 28 '14 at 16:02
  • 4
    Explained why the other solutions did not work for us. And put the code sample on the post. – Vincejtl Apr 28 '14 at 21:19
  • I'm currently trying your solution and so far it looks like to perform well. – AFract Aug 20 '15 at 13:51
  • I didn't checked it in depth but I'm wondering if the optional section " of the web.config isn't intended to do exactly what we expect :) – AFract Feb 03 '16 at 14:15
  • My main question to the above code is: are we not doing something similar to session fixation by dropping AntiXsrfTokenKey to the browser and never renewing it? Can it persist for a year giving this much time to malicious user to weave a new attacking postback form? – Nickolodeon Sep 14 '18 at 13:46
  • @Nickolodeon apologies for the late response. The default value for the expires property of the cookie is DateTime.MinValue. We do not set the expires value, in effect making the cookie a session cookie and will not persist for a year, renewing on each session. – Vincejtl Feb 06 '20 at 02:45
3

I fixed it for now by changing the code to:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    if (User.Identity.IsAuthenticated)
        ViewStateUserKey = User.Identity.Name;
}
Druid
  • 6,423
  • 4
  • 41
  • 56
  • 1
    @Druid I have got same question here apart from putting the above code in Oninit event of base page .. do I need to set viewstateuserkey in any of child pages ..Would you please tell me .... – Glory Raj Dec 13 '14 at 03:30
  • @pratapk As far as I remember, there is no need to set it on every page. – Druid Jan 28 '15 at 06:34
2

Can you turn off ViewState MAC encoding with the EnableViewStateMac @Page attribute?

David Andres
  • 31,351
  • 7
  • 46
  • 36
  • Yes, it works if I do this. I'd rather remove the ViewStateUserKey setting if it's of no use... – Druid Sep 13 '09 at 17:36
0

VERY Strange, I too had similar issue for 3 days and now i resolved it. 1. I had enabled forms authentication and had ssl false

<forms defaultUrl="~/" loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="2880" />
  1. but in my httpcookies tag I had requireSSL=true. Since in the Site.Master.cs it uses cookies to set the ViewStateUserKey, it was having issues

  2. hence I was getting the error.

  3. I modified this to false and restarted web app, now its all good.

Sundara Prabu
  • 2,361
  • 1
  • 21
  • 20