Well I'm totally stumped on this one. Here is the scenario
asp.net mvc3 web application, has been working fine for quite a few months, but I have been going through patches and new releases weekly or so with new functionality. The codebase itself runs on two separate iis7 windows r2 servers. One of these servers, I dont use the standard app pool identity (network service) - I have a specific user, since it pulls some files off a file server, and hence needs specific rights too add/delete from that directory.
On this server, its just started to act crazy with forms authentication 99% of the time in IE9, once or twice I've got to do it on chrome, but chome/ff usually behave themselves no problems.
The problem is as soon as you log in, and go to another page, it keeps responding with a object moved, and redirecting to the login page again. (Sometimes it even does this on logging in) However the session is still valid, because as part of the template, it shows menu items that are based off having the user authenticated, with calls like
Context.User.IsInRole(xxxx)
Request.IsAuthenticated
I've fiddled it, and cookie sessions seem to be fine, everything is being set as it should.
However, if I do a complete iisreset, ie9 will work for about 5 minutes, then it just fails for every request, and redirects back to the login page.
I'm not using iframes at all in the web application, and my web.config settings are
<sessionState mode="InProc" timeout="80" />
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="40" slidingExpiration="true" cookieless="UseCookies" />
</authentication>
Time sync has been checked, and both client(s) and server are within 1 second of each other.
So at this stage, I'm stuck, I don't know where to go to troubleshoot further, or anything else I can try. I can remotely debug the server, if need be.
When I test locally on my dev box, I'm not seeing any issues.
Thanks,
Cameron
Problem solved. I had the number of worker processes set to 2 for the app pool, and hence it was a lucky pot dip as to which of the 2 worker processes had my validated form cookie/session.
Changed back to 1 and the application works as expected. However I'm going to completely rewrite my session handling and store in a db, so I can increase this worker processes to 4 or so to make the app more efficient.
If you are using FormAuthenticationTicket, check below.
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, //version
username, // user name
DateTime.Now, //creation
DateTime.Now.AddDays(5), //<--- THIS Expiration
remember, //Persistent
userdata);
Related
I am working on developing MVC5 application.
I have used session to store user data.
Below is the code which i am using to store session data
if (Session["UserData"] == null)
{
Session["UserData"] = _objLoginSession;
}
I have also increased Session Timeout in web.config, which is as below
<sessionState mode="InProc" timeout="60">
</sessionState>
My authentication mode is also none
<authentication mode="None" />
But when i run my application, it expires with in 1 - 2 minutes only.
Can anyone please guide me on this?
One reason why ASP.NET session might expire that comes to mind is this: session data is kept in memory since you specified InProc mode, so if you recompile your application in Visual Studio or for some reason your application is restarted you will lose session data. And there are plenty of reasons why your application might get restarted by the web server. Things like changing web.config or some files in the bin folder or your computer starts running on low memory.
All those reasons indicate that you should absolutely never (except while developing) keep session data in memory (InProc).
In ASP.NET MVC in one of the WCF services I place an object into the HttpContext.Current.Session object.
When the session times out and the session is cleared of all objects I want to log the user off but have been unable to find a way.
In Global.asax
when the Session_end method is called the Response object and HttpContext.Current are both null.
Any ideas how to log the user off is appreciated.
When the session times out the user no longer exists in any case. If what you are trying to do is clean up open browser windows you would need to implement a timer based on time remaining before session expiration.
SignIn and signout have to do with adding or deleting cookies or tokens to authenticate with an external service. The call that you see should be in the login controller and should not be moved to the global.asax.
No additional action is required.
I think it is wrong practice to try to keep session and authentication cookie in sync. Session and cookie are different things. You can login with multiple users during the same session period. You start a new session when you open some url and it ends when you close the window or it expires on the server side. For more information about session - authentication cookie relationship please read the following answer: asp.net cookies, authentication and session timeouts
Anyway if you want to do it you can use one small trick. You have to periodically call your server with ajax call for example call YourWebsite.com/chcecksession page each n seconds. There you have to check for the existence of a session variable. If it does not exists anymore then simply call FormsAuthentication.SignOut(), refresh your page and the user will be logged out.
I'm not sure about your implantation of WCF as I'm not that versed in WCF. I'm currently building a large scholarship application and we want to restrict logins to a single login per user. I have a table setup to track the userID and a GUID that I store in their Auth Cookie. You could use a session ID instead. I'll be caching the table and refreshing the cache each time I add or remove an entry. I'm using SignalR (you can get as a NuGet package) to maintain connections with each of our clients. When they close their browser SignalR can immediately report that the user is gone and I can terminate their record from the session tracking table. In your case, you could kill the session. Additionally if a user tries to login again, I can see they are already logged in. I then kill their original session and allow them to log in new.
It took a few hours to get used to using SignalR and I highly recommend the videos on Plural Sight.
Set both timeouts in following configuration to exact number of minutes. Make sure you set slidingExpiration to true, that is same as authentication will continue to extend to 30 minutes after each request, as session continues to extend after each request.
<authentication mode="Forms">
<forms loginUrl="~/Auth/SignOn.aspx" timeout="30" slidingExpiration="true" />
</authentication>
<sessionState timeout="30" />
After searching a lot i did not get any answers and finally i had to get back to you. Below i am explaining my problem in detail. It's too long, so please don't quit reading. I have explained my problem in simple language.
I have been developing an asp.net mvc project.
I am using standard ASP.NET roles and membership.
Everything is working fine but the remember me functionality doesn't work at all.
I am listing all the details of work. Hope you guys can help me out solve this problem.
I simply need this:
I need user to login to web application. During login they can either login with remember me or without it.
If user logs in with remember me, i want browser to remember them for long time, let's say atleast one year or considerably long time. The way they do it in www.dotnetspider.com,www.codeproject.com,www.daniweb.com and many other sites.
If user logs in without remember me, then browser should allow access to website for some 20 -30 minutes and after that their session should expire. Their session should also expire when user logs in and shuts down the browser without logging out.
Note: I have succesfully implemented above functionality without using standard asp.net roles and membership by creating my own talbes for user and authenticating against my database table, setting cookie and sessions in my other projects. But for this project we starting from the beginning used standard asp.net roles and membership. We thought it will work and after everything was build at the time of testing it just didn't work. and now we cannot replace the existing functionality with standard asp.net roles and membership with my own custom user tables and all the stuff, you understand what i am taling about.
Either there is some kind of bug with standard asp.net roles and membership functionality or i have the whole concept of standard asp.net roles and membership wrong. i have stated what i want above. I think it's very simple and reasonable.
What i did
Login form with username,password and remember me field.
My setting in web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880"/>
</authentication>
in My controller action, i have this:
FormsAuth.SignIn(userName, rememberMe);
public void SignIn(string userName, bool createPersistentCookie)
{
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
}
Now the problems are following:
I have already stated in above section "I simply need this".
user can successfully log in to the system. Their session exists for as much minutes as specified in timeout value in web.config. I have also given a sample of my web.config. In my samplem if i set the timeout to 5 minutes,then user session expires after 5 minutes, that's ok. But if user closes the browser and reopen the browser, user can still enter the website without loggin in untill time specified in "timeout" has not passed out. The sliding expiration for timeout value is also working fine. Now if user logs in to the system with remember me checked, user session still expires after 5 minutes. This is not good behaviour, is it?. I mean to say that if user logs in to the system with remember me checked he should be remembered for a long time untill he doesn't logs out of the system or user doesn't manually deletes all the cookies from the browser. If user logs in to the system without remember me checked his session should expire after the timeout period values specified in web.config and also if users closes the browser. The problem is that if user closes the browser and reopens it he can still enter the website without logging in.
I search internet a lot on this topic, but i could not get the solution. In the blog post(http://weblogs.asp.net/scottgu/archive/2005/11/08/430011.aspx) made by Scott Gu on exactly the same topic. The users are complaining about the same thing in their comments ut there is no easy solution given in by Mr. Scott.
I read it at following places:
http://weblogs.asp.net/scottgu/archive/2005/11/08/430011.aspx
http://geekswithblogs.net/vivek/archive/2006/09/14/91191.aspx
I guess this is a problem of lot's of users. As seem from blog post made by Mr. Scott Gu.
Your help will be really appreciated.
Thanks in advance.
What you want to do is have a different timeout when the RememberMe option is checked, than when it is unchecked. Unfortunately, the SetAuthCookie method does not allow you to set the expiration manually, so you'll have to do that yourself.
The problem is then, how to do that?
ASP.NET MVC uses the FormsAuthentication class of System.Web.Security to do that, because it's not trivial if you also want to support the configuration settings and cookieless browsing and SSL, but I think that if you simply do this:
int timeout = rememberMe ? 525600 : 30; // Timeout in minutes, 525600 = 365 days.
var ticket = new FormsAuthenticationTicket(userName, rememberMe, timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);// Not my line
cookie.HttpOnly = true; // cookie not available in javascript.
Response.Cookies.Add(cookie);
...you'll get a basic version of what you need.
NOTE: I did not test this code.
Kevin and Dave,you guys rock, man.
Dave, in addition to your code i had to add one more line to make it work. I mean to make it remember for at least one year. I had to assign value to cookie.Expires in addition to your code to make it work. If this line cookie.Expires is not set the cookie is lost after computer restart i mean at the end of the session. I noticed this in FireFox. I Went through the details of cookie and i found: If cookie.Expires is not set then value for "Expires:" attribute in Firefox is "At the end of the session" but if cookie.Expires is set then the value for "Expires:" attribute in Firefox is to the datetime the cookie.Expires value was set.
Here is the code:
int timeout = createPersistentCookie ? 525600 : 2; // Timeout in minutes,525600 = 365 days
var ticket = new FormsAuthenticationTicket(userName,createPersistentCookie,timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);//My Line
HttpContext.Current.Response.Cookies.Add(cookie);
Thank you guys, that was really a great solution.
Just a quick note about using membership auth ticket in a shared environment for anyone who may land here with that issue. I've got an mvc site runnig at godaddy and had trouble with remember me. This was the solution:
<system.web>
<machineKey
validationKey="4C6404A3B305CD6E8CFEAC258F042FB95E45E9C3C2CEC3AAB838996CFBE661E41DF1A1BAC75B9B45E02147612FD9B71CA74DDA50B0D0D6ED11F0BB8E31048953"
decryptionKey="BC471CF17A97B08A9DF85C7B502AD95680E3BE4418FD9C6CEA57E7F97ED64291"
validation="SHA1" decryption="AES"
/>
Thanks to :
http://www.geekfreeq.com/aspnet-remember-me-option-forms-authentication-not-working/
That's not a problem, it's a feature :)
The user's session hasn't expired yet so, even if they close and reopen the browser, the cookie is still good.
It's the cookie's expiration that invalidates the user's session.
I had implemented same thing and when i test it it works fine in Mozila but not working in IE8 for all pc, i also had updated setting to accept cookies in IE but still not working.
Internet Explorer 8.x
Click on the Tools-menu.
Select Internet Options in the menu - a new window opens.
Click on the Privacy tab near the top of the window.
Click on the Default button of the window.
Move the slider so that it is on one of the levels below Medium High (including Medium, Low, Accept All Cookies).
Save changes by clicking OK.
You should be able to add items to your shopping cart now.
As a user, when I see a "remember me" checkbox, I expect it to remember me -- not just when I close my browser, but when I come back to the site after a week.
So in my ASP.NET MVC application I am considering the following web.config values:
<authentication mode="Forms">
<forms defaultUrl="/" loginUrl="/account/login" name=".ASPXAUTH" timeout="50000000" />
</authentication>
I plan to also have userIsOnlineTimeWindow="20" to still have decent stats about who is online. I also plan to setup a machineKey so that the user isn't kicked off when IIS recycles.
Thoughts on this setup? My biggest concern is that it will hog up resources -- but will it in a stateless MVC app? Isn't that actually related to the sessionState timeout variable as opposed to authentication timeout? And sessionState is no longer relevant in MVC? I've seen conflicting information and am trying to get to the bottom of it.
Also, if I take this approach, I assume that this should also take care of the user who fills out a form for a long time before hitting submit and they lose their work. I've seen posts related to that, but am trying to solve two problems at once (keep alive while viewing the page plus also keep alive for days if I said 'remember me'.
One issue I see is that even if the user doesn't say "remember me" it will still remember them until they close the browser. (To me that's within user expectations.) The other issue is that I may need to perform extra checks on IsApproved and IsLockedOut per http://scottonwriting.net/sowblog/posts/11167.aspx.
Thoughts? Particularly on the system resources issue. Thanks.
FormsAuthentication is stored as a cookie in the client's browser and will not use up any resources by itself. The timeout setting there does not change how long something will be kept in the server's memory or anything to do with the regular session storage.
If you rely solely on the user ID/name you get from FormsAuthentication (HttpContext.User) then yes, there will probably be issues with administering user accounts like you point out. It would be a good practice to look up the actual current user data once per request.
I've got an app built using asp.net mvc and deployed over 2 Amazon EC2 instances. I'm using forms authentication to authenticate users. I simply make a quick look up on the given username and password and if I found a match I set an authentication cookie, like so:
if(_repository.Login(username, password))
FormsAuthentication.SetAuthCookie(username, false);
This works fine as long as the application on one machine, but, once I leveraged Amazon Elastic Load Balancing to deploy the site on two machines, the site behaves in a very weird way. When a user logs in, the site recognizes a logged in user, after a refresh or two, the site no longer see the user as a logged in user. If the user keeps refreshing again for some time, the app sees the user as a logged in user again, and this goes forever.
I'm aware that such a problem might occur if I'm storing SessionState inproc. I'm not using SessionState at all.
What am I missing here guys?
Ps: I've edited the session state to be stored on a state server [Though i'm not using neither sessions nor TempData anywhere on my app] and the same weird behavior is there.
You need to synchronize your <machinekey> between all servers in your farm. Otherwise the forms authentication ticket is only good for the machine which issued it. I doubt this has anything to do with Session/TempData.