Downside to Forever Timeout in ASP.NET MVC? - asp.net-mvc

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.

Related

Log a user off when ASP.NET MVC Session expires

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" />

asp.net mvc 3 forms authentication and ie9

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);

MVC: logged in, but no session vars?

I use chrome as debugging browser.
When I start my MVC (Razor) website, click the stop button and the website keeps running in chrome ,while I can make changes in VS ... perfect.
But sometimes (due to I don't know what changes), when I refresh a page, I'm still logged in, but I looses all my session vars.
How can I catch if session vars is cleared, so I can take my users back to login page? (I need a kinde global.asax page_request method.
I do have the .. <forms loginUrl="~/Account/LogOn" timeout="2880" /> ... but Im not logged out - only session vars are cleared.
It's because your login state is persisted in a client cookie. The session state is persisted on the server in memory (or whatever). When your app restarts the session is cleared but the user still has a valid forms authentication token (assuming forms authentication here) on their machine. Forms authentication does't use session in any way by default.
So, at the beginning of the request, you can either reload the user session from the database when it's null (I think this is the preferred approach if possible) or redirect the user to the login screen with a message saying "ooops, sorry we've lost your session" (which is not good!)
If you use the built-in Authorization functionality, you can just add the [Authorize] attribute. There's some info on using custom authentication here:
ASP.NET MVC Authorization
Lee Gunn explained it well. One solution would be to create a custom filter attribute similar to Authorize that verifies the session has the values you're expecting and decorate the appropriate controllers/actions.

ASP.NET MVC Object locking mechanism

I'm working on a ASP.NET MVC 2 web application that lets users edit parameters on a simulation and launch it. Once a user starts editing a specific simulation, it must be inaccessible to other users.
Is there an easy way to achieve that goal in ASP.NET MVC?
My first idea was to put the logged on user's identity in the Application collection, along with the simulation:
Application.Add((Guid)Membership.GetUser().ProviderUserKey, simulationId);
Then I would remove it in the Session_End method, when the session expires. However, the Session_End method is never called with those parameters in the web.config file:
sessionState mode="InProc" timeout="1"
What am I doing wrong? / Is there a better mechanism?
Hard to do in a web application. Can you tell us why? usually collision detection is used in this instance and the first updater wins. The second updaters can either be told "refresh your data and retry" or you can try to apply or merge the changes and offer to save the newer version.

RememberMe with DotNetOpenId in ASP.NET MVC

Using DotNetOpenAuth 3 in ASP.NET MVC and implementing a RememberMe facility ...
I'm finding that even if I set createPersistentCookie to true in FormsAuthentication.RedirectFromLoginPage and FormsAuthentication.SetAuthCookie the user is not remembered once the ASP.NET session times out.
If I inspect the cookie I find it is marked as persistent and does have an expiry date way in the future, I assume because I set my web.config FORMS timeout to a few years away. Anyhow, if the user closes the browser and re-opens it they are remembered correctly - as long as the ASP session hasn't timed out.
An older post of Scott Hanselmann's makes me wonder if it is because FormsAuthentication tries to renew the authentication ticket and maybe in an OpenId model that doesn't work but I have set FORMS SlidingExpiration="false" in web.config and anyway I thought that forcing a persistent cookie would make that stuff irrelevant.
I'm also wondering why the DotNetOpenId MVC sample doesn't include a RememberMe checkbox - maybe there's something tricky about it?
On the other hand, here at StackOverflow I see I am automatically remembered across sessions. Wondering whether they used something other than DotNetOpenId to do their OpenId authentication.
Anybody else done RememberMe successfully with DotNetOpenId in ASP.NET MVC? Any tricks?
[Update]
Thanks for trying to help, Andrew. Turns out this was not about DotNetOpenId.
I gather, after reading this, that my hosting provider is probably recycling the app pool regularly and that's causing the authentication ticket encryption to be done with a new machine key.
As per the preceding linked article I added the following under System.Web in my Web.Config and it resolved the issue:
<machineKey
validationKey="(generated a new key to place here)"
decryptionKey="(generated a new key to place here)"
validation="SHA1"
decryption="AES" />
I still think the cookie name should match... but here's something else.
It sounds like you're saying as long as your timeout in the web.config file is large, then things work. But that once you shorten it, your persistent cookie doesn't outlast the timeout value. This forum topic helped answer this for me:
http://forums.asp.net/p/1010241/1347970.aspx#1347970
It seems that the timeout in web.config affects all cookies. It says how long the authentication ticket lasts. All auth cookies have this 'time to live' timeout whether they are 'persistent' or not. So the difference between persistent cookies and non-persistent cookies are that the former will last across different browser sessions and the latter will die (early) if the browser is closed.
Does that make sense?
Does the cookie name match in your web.config file and your controller's call to FormsAuthentication.SetAuthCookie? This may be a bug in the DNOI sample, but I suspect if you have a cookie name in your web.config file (as the DNOI sample does), then you probably have to set the cookie name as the third parameter to SetAuthCookie or RedirectFromLoginPage. Otherwise, forms auth doesn't recognize the persistent cookie you set as the login cookie.

Resources