I have an C# ASP.net website hosted with www.blacknight.com.
Sometimes when I login to my website I get the following error:
This happens in about 1 in ever 10 login attempts. I have contacted them and they assured me that its not hosted on a Web Farm or cluster and to check my ViewState.
Does anyone know what could be wrong here? I cant reproduce it everytime so its hard to track down.
Please see the KB article at http://support.microsoft.com/kb/2915218 for a resolution to this issue. In particular, you should set an explicit <machineKey> element in Web.config.
Appendix A of that article tells you how to generate a <machineKey> element.
Never set EnableViewStateMac=false. And you should never use a key that you got from a third-party generator. Only use one that you generated yourself.
Is it possible that IIS is recycling your application between the original page load, and the login attempt? If you don't specify a <machinekey /> in the web.config, a new machine key will be generated on application start up. And then, when you attempt to validate the viewstate that was generated on the old machine key during post back, this exception would be thrown.
Related
I am playing around with aspnetboilerplate.com's template for dotnet core. What I am trying to do is to deploy the template on a shared hosting (windows) server running Plesk (note, I have no control over the server at all).
The template works perfect locally, can log in, add users, roles, etc. Deploying it the shared hosting server gave some issues, but that was resolved relative quickly (configuring for dotnet core and had to drop to dotnet core 2.1 as 2.2 is not yet supported on the server).
The problem now is after logging in, within a minute I re-directed to the login page. I have had a similar problem with ASP.NET MVC5, but providing a Machine Key in the web.config and making use of a database for session data fixed that problem. So I am reasoning it is the same problem with the dotnet application.
But seeing as dotnet core does not use machine keys and DataProtectionApis a different approach is needed.
So I have tried adding services.AddDataProtection(); to StartUp.Configure()
I have read Distributed caching in ASP.NET Core and just about all the links coming off there as well as tried multiple code examples, but either I do not know what I am doing (high probability) or I am not doing something right.
So, how do I prevent the user being signed out unexpectedly using dotnet core 2.1 on a shared hosting server?
EDIT - 2019-01-25
Some new information: Tried setting timeouts as suggested, but this either does nothing or is not possible. For the dotnet application to run on Plesk, I had to disable ASP.NET support so that .NET core gets No Managed Code Application Pool. Trying to access ASP.Net settings on Plesk the (where you'd have access to Application Pool setting, etc) gives an error saying 'ASP.NET support is switched off for this website'.
One thing that does not happen is the App_Data/Logs folder never gets created when publishing. I had to manually create and set permissions so that log4net can create a log file. The log file provided me with additional information:
ERROR 2019-01-25 09:33:03,005 [6 ] .Antiforgery.Internal.DefaultAntiforgery - An exception was thrown while deserializing the token.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted. ---> System.Security.Cryptography.CryptographicException: The key {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} was not found in the key ring.
Searching for this error only once again lead me to documentation about adding services.AddDataProtection() to the ConfigureServices method, but this drones on about Azure Key Vaults (or other external providers) or writing info to a shared UNC so that other servers can access cached key info (and this is probably what I need). But seeing as all of these options are not available to me, I found an extension method which allows the key to be stored on an MSSQL server. Busy setting this up now to test.
If anybody wants to give their opinion, please be my guest.
UPDATE 2 - 2019-01-25 - SUCCESS (for now)
It would appear that making use of DataProtectionAPI is the way to go. Logs are not reporting any AntiforgeryValidationException, yet. I am going to let it run for a while and if all is good, I'll post the solution and how it has been implemented.
Based off the information you provided above, I believe your session is timing out.
When the session times out the user will be redirected to the login page to reauthenticate. I am not overly familiar with plesk but from very quick googling it seems that you should be able to increase the session timeout.
Of course, if you are setting the sessiontimeout yourself in configurservices you could just adjust it there as well I would assume (again unfamiliar with the plesk setup fully).
If you do that, the problem should resolve itself. Perhaps the session timeout is set to a short time period for testing?
.net session state
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
});
As PersistKeysToSqlServer is not supported in dot net core 3.1, we can use .PersistKeysToDbContext<AppDBContext>() or PersistKeysToFileSystem as it is shown here.
The problem, it turns out was not the session expiring, but rather, when another server takes over the load of the my site, it has no session context. Data Protection services allows for the creation of a database to store session info in and it shared across servers in the farm. Similar to the session state attribute from web.config in MVC projects:
<sessionState mode="SQLServer" sqlConnectionString="Data Source=000.000.000.000;Initial Catalog=session_db;User Id=user;Password=password;" allowCustomSqlDatabase="true" timeout="480" />
This is how I solved the problem:
Within ConfigureServices I added:
services.AddDataProtection()
.SetApplicationName("MyApplicationName")
.SetDefaultKeyLifetime(TimeSpan.FromDays(14))
.PersistKeysToSqlServer(_config["DataProtection:SqlServerConnectionString"]);
I also had to create a separate database which is responsible for storing the session information. The DataProtextion:SqlServerConnectionString is an entry in the appsettings.json file:
"DataProtection":
{
"SqlServerConnectionString": "Server=server; Database=database; User=user; Password=password;"
}
There are ways to probably solve this problem (eg with Redis), but seeing as I have no control over the server my site is hosted on, Data Protection services works just fine.
I have just released one of my application to production environment. Live environment has two IIS Servers via a Load Balance. The server configuration people has informed that they have implemented something called "Sticky Load Balancing" to carry out the sessions to IIS 1 or 2 via the Load Balance [Sessions are handled via the Load Balance].
Error
On accessing the website via IE9, I am getting a view state error. Screen Shot attached.
Exception
The exception is not being generated from Chrome Browser. But compliance requires us to tweak the application to IE9 only.
What Needs to be done to resolve the issue ?
The below post, although the person who asked it is not exactly facing the same situation, The solution which has been posted is valid for this, Especially the second point which says about defining a machine key for the application.
Please refer the below, i hope it helps.
Avoiding invalid viewstate when deploying on a load balanced website without downtime
Our operator has implemented a Round Robin load balancer on our web portal and it seems to be causing some problems I can't get to the bottom of.
I'm able to identify which server we're on and as we navigate around the site we stay on server A. If I leave it for 5 minutes and try another page I'll get pushed to server B, logged out and shown the log in page.
I've got them to make sure the MachineKey in the machine.config is the same on both servers and I've tested locally that the session isn't being used - I can turn the session off completely locally and it still works. I've verified on both servers it is creating an ASPXAUTH cookie on the domain so we should be classed as authenticated on both servers - but keep loosing my authentication every time I change server.
Any ideas on what could be causing the logging out? I'm guessing it's my misunderstanding about how ASPXAUTH works.
Sessions are handled separately from Forms Authentication. There is a good explanation of this here.
The most common reason for Forms Authentication failures on load-balanced environments is lack of synchronization of the MachineKey element. You've stated that you've got the server operators to ensure that the MachineKey is synchronized, but have you verified this yourself in some way? Is this the case on ALL the web servers? From previous dealings with a couple of commercial web hosts, I've found that it is (unfortunately) difficult to take their assurances at face value.
Another thing to check is if the FormsAuthentication configuration (timeout, path, name, etc.) is the same on all of the hosts.
Are the patch levels the same on all of the hosts? You might want to see if the compatibility switch mentioned here is applicable in your situation.
Assuming that the hosting setup is correct, maybe you have initialization code on the page that logs you out if some condition is not fulfilled?
Try to take a look at the server logs and trace the sequence of HTTP requests involved during a failed page request. That might produce a clue.
Edit: This guide to troubleshooting Forms Authentication problems is detailed, and quite helpful: Troubleshooting Forms Authentication
Check for any other application functionality which depends on cookies. The web server on Server B will not recognize cookies that came from Server A. If any part of your authentication depends on cookies being populated, then that could cause your problem.
You have probably already ensured that the domain used for cookies is the same on all of the load balanced servers, but I thought I'd mention that. If the domains aren't compatible, then the browser will simply not send cookies to the server.
I got this error when i access my hosted web application(in VS2008 C# ASP.NET 3.5 Framework)
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
The interesting thing is that there is no problem if we continue after login process. If you logged in and do nothing for 15 or 20 minutes, then click any menu...this error will be generated. So I doubt that it is related to session out. In my webconfig file I have written session time out as follows.
<sessionState timeout="15" />
How can I correct this error?
There are a few ways to fix this issue, but some solutions are better than others. The fastest way is usually to add the following to the web.config:
<pages enableEventValidation="false" viewStateEncryptionMode="Never">
The problem with the above solution is that you sacrifice some security. The next "quick fix" is to add the following to the web.config, but there are drawbacks to this as well:
<pages enableViewStateMac="false">
If this application is hosted by a web farm or is otherwise distributed across multiple web servers, you should probably steer clear of that option.
In my opinion, the best overall solution is offered here.
I believe that your problem is in App Pool "Idle timeout" field.
You have to ask to your provider to change it to something greater... say 20mins
Take a look here.
What different ways are Machine Keys useful in asp.net?
I think the following are correct but thought there may be more.
Multiple applications can use the same cookie
Multiple servers can work with the same viewstate
MachineKey is used for:
ViewState encryption and validation
Forms Authentication (or Federated Authentication) uses this key for signing the authentication ticket
Having a Web App installed on multiple servers requires same Machine Key configured on all of them in order for Load Balancing to work.
To see all details, please refer to: MSDN How To: Configure MachineKey in ASP.NET 2.0
Machine key is also used to encrypt/decrypt the webresources.axd parameters.
Even on a single server the machine key should be configured, because any recycle of the app domain will generate a new key when it is set to auto. This causes the next postback just for pages rendered before the recycle, to cause a viewstate validation error, and also issues with the resources during that time.
Encryption - very common.