Setting ViewStateUserKey gives me a "Validation of viewstate MAC failed" error
Asked Answered
S

6

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?

Stratfordonavon answered 13/9, 2009 at 17:4 Comment(0)
C
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.

Carty answered 30/9, 2010 at 2:3 Comment(2)
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.Carty
This was very helpful. I didn't know that ASP doesn't keep session if nothing saved in the it.Agle
P
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

Pace answered 28/4, 2014 at 15:38 Comment(6)
Could You please, elaborate more? Not only links.Abirritate
Explained why the other solutions did not work for us. And put the code sample on the post.Pace
I'm currently trying your solution and so far it looks like to perform well.Hildick
I didn't checked it in depth but I'm wondering if the optional section <machineKey validationKey.....>" of the web.config isn't intended to do exactly what we expect :)Hildick
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?Subjection
@Subjection 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.Pace
S
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;
}
Stratfordonavon answered 13/9, 2009 at 20:1 Comment(2)
@Stratfordonavon 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 ....Winnah
@pratapk As far as I remember, there is no need to set it on every page.Stratfordonavon
P
2

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

Psi answered 13/9, 2009 at 17:30 Comment(1)
Yes, it works if I do this. I'd rather remove the ViewStateUserKey setting if it's of no use...Stratfordonavon
B
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.

Bascom answered 16/2, 2015 at 8:0 Comment(0)
D
0

I had a similar issue. The code I was modifying wasn't mine. I added the cross site scripting code to the app I was working on and others. The one I had the problem with was changing the submit action to a different page. The submit (in my case) was unnecessary, so I changed it from form.submit() to window.location.href. Problem solved.

Dessiatine answered 13/3 at 0:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.