Shamil Salakhetdinov
shamil at users.mns.ru
Tue Dec 18 18:48:47 CST 2007
Hi Gustav, It looks like I have found a rather generic solution - here it's: Requirements: ------------- Allow ===== - to have multiple tabs opened for a browser instance for a logged-in user: all tabs will share the same login and Session id (this login/sessionId sharing is a feature by design of browsers, ASP.NET, forms authentication, custom functionality) - a session of an abandoned browser to expire in 15-30 minutes and then another session can be started with the same login or - "optionally kill" active login's session - first informing the user trying to use login, which is currently used in an active session that his attempt will "kill" active session, which he probably abandoned (by mistake) without explicit logout ... Prevent ======= - to use the same login with another instance of a browser running on the same PC; - to use the same login on another PC, while this login is active (logged-in) somewhere else; - running (loading, rendering web page) by copying & pasting URL from one tab's window to another tab within one browser instance or to another browser instance... To implement above requirements I plan to: ------------------------------------------ Before navigating to a URL with my Web App: =========================================== - prepare context parameters to put them in the URL's QueryString to keep initial rendering state/context for a Web Page to be navigated/transferred; - generate a unique hash for the QueryString using the following values: 1) Login name; 2) login timestamp - created on login and stored in Cache using login name as a key; 3) The session navigation step Id (navid) - unique sequential number incremented for every Redirect/Transfer and kept on the Session level; 4) SessionId (the fact is that Sessionid can be the same for logins/logouts for the same/other logins when these logins are happening in one browser instance...) This hash will be added to the QueryString together with navId; - make an URL with parameters and navigate/transfer to it; On page loading/building on server side I will: =============================================== - use generated hash to create Session[...] item key on page's first load within given context (!Page.IsPostback); - if the same query string will be used (copy & paste) on another *tab of the same browser instance* then I can check that this hash was already used (by reading Session[...] item) when rendering the first page and I will cancel rendering of the second's tab page.... - if the same query string will be used (copy & paste) on another *instance* of a browser then by recreating hash I will see that it will not fit the SessionId and I will cancel rendering page on the second browser instance... - IOW this hash will be a good measure to prevent compromising the QueryString values... - the Session[....] hash value has to be cleared out/saved in db when navigating to another URL, that will not always be possible, but that should be rare occasions and therefore I expect there will be not be that much "hanging abandoned hashes"... Additionally ============ - to prevent copied & pasted URL with QueryString parameters to be used within the same browser instance when first page is navigated out I can keep hash saved in the db table and this table's data used for the check described above. This table's data will be cleared when session ends/expires or this data can be used as a navigation audit trail... Summary ====== It looks like I covered all the possible variations - still the above solution is rather simple to implement and it's scalable... Currently I will just use QueryString to keep navigation context: QueryString is known as being an insecure for compromising attempts but because of the fact that I plan to add a hash to this QueryString in (the near) future I will keep it secure: and the hash calculation/check will be done in the generic part of my code as well as mentioned above navId caluclation, as well as keeping session login timeStamp in Cache[...], as well as keeping page rendering hash in Session[...], as well as clearing Session[...] hash/saving it in DB when navigating out or when session gets expired... Final note: =========== Originally I planned to stop using QueryString because it's commonly accepted as insecure but the solution above allows me (?) to continue using it (QueryString) without that much additional efforts and having it good enough secured (I have a Web app under development, which has different user contexts depending on roles and these contexts' can be dynamically changed without logging-out/-in, and users are rather inexperienced, and this application have to communicate with external credit card processing server, and this application should have easy navigation, and this application should place consistent orders, which are generated from shopping cart(s)' items, which in turn are collected in different contexts in which e.g. a user can be an admin making an order for a customer who in turn purchases a service for another customer who should be able to see this to be purchased service as owned by his account when purchase completes but the first customer should have this service paid from his accountetc... Because of this relative complexity of the app I looked for a solution, which is presented above, which isn't contradictory (?) and which is not that a big issue to implement generic way.... Being here now I will probably even weaken the requirement stating to not let an URL with QueryString parameters to be copied & pasted and activated (corresponding page loaded/rendered) within tabs of one browser instance: I will let to do that except just one case when application redirects to an external credit cards processing service - this service should be redirected only once within check-out process and until it calls back transaction is not finished... -- Shamil -----Original Message----- From: dba-vb-bounces at databaseadvisors.com [mailto:dba-vb-bounces at databaseadvisors.com] On Behalf Of Gustav Brock Sent: Tuesday, December 18, 2007 8:27 PM To: dba-vb at databaseadvisors.com Subject: Re: [dba-VB] ASP.NEt 2.0: Forms Authentication: how toprevent using the same login *second* time from another PCwhen this login is in use in active session? Hi Shamil Oh, that is a nightmare. I just opened three tabs (it's me at 213.150.48.58) and the only parameter changing is Page View Count. And that counts up also if the user requests a refresh of the browser window! And it counts down as the sessions time out. Not very useful. So now what? Could a client side GUID be generated that was recorded at server side? Sadly, I have little time to work intensively with this right now - a web session on the new MySQL Falcon engine is approaching - but count me in if you need further testing - it would be really nice to find out how to deal with this issue which will pop up again and again. /gustav >>> shamil at users.mns.ru 18-12-2007 18:02 >>> Hi Gustav, OK, killing session when simultaneous FormsAutentication login with the same credentials happens or wait 20 minutes this is one "programmers' nightmare" issue, and here is another one: - in IE7 (or FireFox 2.x +) you can open several tabs in one browser instance and then all these tabs' windows will share the same session... How about that "nightmare"? I have got deployed here http://shamils-4.hosting.parking.ru/Sessions a sample from this article http://www.stardeveloper.com/articles/display.html?article=2002102501&page=1 by setting session time-out for three minutes <sessionState mode="InProc" cookieless="AutoDetect" timeout="3" /> just for testing purposes to see how sessions expire and how one browser's instance tabs share the same session ID... Now imagine a Web app having context (i.e. some internal state) and a user opening several tabs in one browser instance and copying and pasting URL "to see what happens" or to maybe do several tasks with the same Web app having issues the *same* session Ids for one login, which could be working on one task when this user switches and prepares another. When FormsAuthentication added then user *will not* need to login again if he copy and paste URLs in windows of the different tabs of the same browser instance... Server side app will not be aware how many windows are opened on client side without special measures... What those measures should be to differentiate calls coming from different windows having the same URL, same session Id, same Forms Authentication cookie? I currently see the only "simple" solution to have hidden HTML field(s) with some IDs for every page returned from server to browser, and when browser posts back such page then this ID expires and is changed to another, and server side app has to keep track of these custom IDs, and when they are sent via callback remove them etc. ... -- Shamil -----Original Message----- From: dba-vb-bounces at databaseadvisors.com [mailto:dba-vb-bounces at databaseadvisors.com] On Behalf Of Gustav Brock Sent: Tuesday, December 18, 2007 7:21 PM To: dba-vb at databaseadvisors.com Subject: Re: [dba-VB] ASP.NEt 2.0: Forms Authentication:how to prevent using the same login *second* time fr Hi Shamil That was my thoughts and conclusion. And it does have that complication. However, at _any_ time the user can "pull the plug" - in many ways with or without intention. I think that's the programmer's nightmare all the time to consider "what happens at this point if the user session is killed?". The user may loose data typed in, but the app should not crash and stored data should not get corrupted. Further, you cannot educate users to always logout clicking a button. As the good guy I am I always try to do so, but in Hotmail you are redirected to msn.com which I hate, thus I always close a Hotmail session by clicking the close button of the window, and most users will do as well as they forget or don't understand why not to do so. Also, your client must be really nice and patient! Keeping a user logged out for about 20 minutes if something happens will not raise popularity among users. Again, users are impatient and will not understand why they can not just log in again. /gustav >>> shamil at users.mns.ru 18-12-2007 16:52 >>> <snip> ...the most user-friendly looks like to "kill" existing session when a login with the same FormsAuthentication credentials happens - this should be a rare occasion after all and this will not force users to wait until session time-out expires... ...the only complication for the latter approach is that Web application keeping some state information should be ready to be "killed" any time - I mean when they get "killed" they shouldn't leave the system and back-end database in inconsistent state - the "killer: should be able to "catch-on" on the session it "kills"... ...yes, I know web applications should be better programmed completely stateless - trying to achieve that here but not yet there - have to convince customer to change the ways they usually work with desktop apps - I mean to not expect the same "stateful" behavior from Web apps because "it's all two blades sword" - you gain in one feature/functionality/usability issue - you loose in another... </snip> _______________________________________________ dba-VB mailing list dba-VB at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/dba-vb http://www.databaseadvisors.com