I'm fairly new to using Forms Authentication and am trying to wrap my head around how this all works. Basically, what I'd like to be able to do is store some user data that is associated with the FormsAuthentication ticket (data that comes back from my ldap server); however, I don't want to actually store this data in the cookie as it could be a rather large amount of data. Is it somehow possible to store this information in memory on the server, but keep it strongly tied to the ticket so that if the user times out or is logged out the data is destroyed as well. I realize I could use session variables to do this, but this seems awkward as I'd have to manually clean up the session variables if the user logs out. Is this possible or does this even make sense to do?
Why would you have to manually clean up a Session? The entire purpose of the Session dictionary is to allow you to do exactly what you want to do here: associate some known data with the user's current browser session. When the user's browser session ends for whatever reason, the HttpApplication and its Session are orphaned and GCed. So, I would just put your LDAP data into Session under a key, or set of same, and forget about it.
Related
I've a pretty basic question related to user profile storage along a session.
Let's say that I've an Account table that stores user profiles and that I've linked this table to ASP.NET SimpleMembership. Once a user is logged in, controllers may need to retrieve information in or based from her Account. What I'm doing right now is querying the database each time I need data, with something similar to this: _dbContext.Accounts.Where(a => a.EmailAddress == User.Identity.Name).Single().
But I'm afraid that this may cause unnecessary load on the DB and think that a better idea (perhaps it's what everybody does!) is to store the Account object in a Session variable once a user logs in, enabling direct access without re-querying the DB.
Is this the usual way to do it? Isn't there a risk of "de-sync" between the Session variable and the authentication?
Thanks
Our website uses this same type of method for a user-type object at login. Upon confirmed login we store the user object in a session variable. If something is changed or updated the object is updated and depending on the circumstance the change is updated in the database as well (timing meaning update immediately following the change or, after gathering a group of changes).
It just depends on how complex your system is. Ours is fairly complex, and this has proved to be a pretty solid way - without requiring constant maintenence and updates.
What we have currently implemented works well but I'm just concerned that there maybe a better way or we are doing it completely wrong.
Once logged into our website, on each and every request it will make a request to the API to get the users details.
E.g. Username, ImageUrl, Roles / Permissions, Email Address etc
It then stores this data in the BaseController for the viewpage or anyone else to see during that request.
Upside:
to doing it this way is that you know each request that the users permissions/roles and their details are all up to date!
Downside:
Your most likely to get exactly the same data every request, until that one day they change their details. Thus your possibly making unnecessary calls??
However the first way we tried all this was when the user logged in all their data gets stored in the cookie, the problem with this is that our users hardly ever logout so all the data that is stored in the cookie gets stale often. -> Stale Roles/Permissions is an annoying issue!!!
How does everyone get around the stale data from login.
I would go back to your initial approach of storing the claims inside the cookie.
If you do indeed have very long log in times then I would guard against stagnant claims by periodically refreshing the cookie.
If you are using forms authentication then you could intercept the FormsAuthentication_OnAuthenticate event in Global.asax, decrypt and manage the cookie (here), validate the user and cookie first then run a quick conditional check against a custom field in the userdata property, called refreshedDate.
If the last refresh date or creation date is greater than some configurable window then call to the database and refresh the claim data from the database. Finally update the refreshDate and claim data and update the cookie.
Update
Following on from your comment...
Just to say that it is not uncommon to hit the database for each request, that is to say I have known it happen in a number of production systems. Many people are probably using ASP.NET session state using MS-SQL database's. Typically I have seen it when there is a real security need to invalidate someone's session, deny access and log them out immediately.
If your database is on the network locally to your web servers and/or latency is acceptably low then it can be a perfectly workable solution. Just make sure your database queries are minimal and performance tuned to perfection, consider side steeping any ORM (if applicable) and use raw SQL connections to make things as fast a possible.
If database latency is high, the other middle ground solution is caching, using Redis or Memcached to house the results of your queries and invalidating the cache when permissions are altered etc... but obviously adding the required infrastructure and operational support for caching solutions is a serious consideration.
You can apply an expiration to the cookie; that way it dies and requires them to login. Or, keep their user ID in the cookie, but store their profile info in session. When session dies, the next time the profile is checked if it is null, make a query to the API again. This way, it's getting updated more frequently.
In addition to other suggestions, another option may be to use a notification mechanism from the underlying role/permission store whenever a user's data changes. This notification could then be used to invalidate the cached data on the web server. This would ensure that the cached data is returned in the majority cases but the store would then be hit only when the data had changed.
If the underlying datastore is SQL Serevr then consider something like SqlDependency.
This is obviously a more complex architecture but it would meet your requirement and only you could say whether it's worth the effort / complexity / tradeoff!
In order to mitigate potential Session Fixation/Trapping attacks, we need to be able to transfer the ASP.NET session state from one session Id to another after a user successfully logs in. A user has important session information before login that needs to be transferred, so we cannot just call Session.Abandon or Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", "")) as all the session state is lost. We can use System.Web.SessionState.SessionIDManager to call CreateSessionID() and then SaveSessionID() to generate a new ID, but again, the prior state is lost on the next request. So my question is basically how to transfer/correlate session state from a pre-login session Id to a post-login session Id.
There are multiple articles and posts around that explain the potential issues with using Session state. The most obvious is problematic support for multi-server environments.
If you store the items that you're currently putting in Session[]in a database or use SQL-based sessions, "transferring" is simply a matter of associating a user or connection with a particular record set.
If you bypass the Session object and handle everything yourself, which is a trivial task if you want to maintain the simple Session[] key-value interface, you get a number of benefits, such as settings that persist between sessions and across applications (as long as they share a common database).
we have a asp.net application which use session (in-proc) for single user across pages, now they want to keep the data (eg. a shopping cart) more persistent, even they leave the web app, means close the browser, next time they login use same id, they want the data back, any solution in ASP.NET?
If we save session in sql-server which I think is an option by microsoft, but I am not sure if it works even after user leave the app, or close the browser
Session data is meant to only persist for the lifetime of that browser session.
The answer is to not save the data in session, save it in the database in ShoppingCart and ShoppingCartItem tables instead. These will persist as long as you want them to.
The ShoppingCart table would have a UserID column that is FK to your User table.
You'll need to construct a relational database and store the entries in there.
Granted, the Application scope is higher than Session, but it will only exist for the life of the application pool. It sounds like you're looking for permanent storage.
I've seen shopping cart system using cookies instead and some using both cookies and database.
Cookie only: The "official" size of a cookie is 4K
Cookie + database: Store a GUID in the cookie and use it as a reference in the database
But... I think that storing shopping cart in a cookie or a cookie/database is not very user friendly. I do prefer that the website forget my shopping cart if I leave. I'm annoyed when website store such information with my approval.
You will need to use a database to mirror the data contained in the session, that way the data will persist long after the user logs off, if the application is restarted, or if the server is restarted. You could save the session object into sql-server as a binary object and serialize/deserialize when needed, but how do you know when to do the initial serialization? It's hard to tell when a user has logged off if they close the browser window.
Storing the session object as a single column might work in the interim, but in the long run you will probably want to come up with a proper relational design and store data in columns in tables, that way you can run queries and reports against the "work-in-progress" shopping carts (such as: how long do people let a shopping cart sit before finally checking out?).
As others have mentioned, cookies are another option but those exist on the client side, and if they decide to clear cookies (a lot of tech support people seem to give this advice as the first response when users complain about slow browsers), the shopping cart is lost.
I've got an existing site I'm taking over, and right now it stores, in a session variable, the id of the currently logged in user (if logged in at all -- otherwise I'm sure it is empty string or null or something).
The client now wants, after someone is logged in, to "keep" them logged in on that computer for an indefinite amount of time.
ASP.net Sessions have a maximum idle time of 1 day, I believe. The website isn't written all that well in the Flash portion (whole front end is flash) and the flash will process a login, then, as long as the flash isn't reloaded, assume that the user is still "logged in".
I think my solution is to ALSO store a client side cookie with some GUID value and hold in the database the associated user id...sort of like a session that never expires. So, when the page is loaded, I can check my cookie, use that to select the userid out of the database, and if we find one, then set the session value that says user 23 is logged in.
Does anyone see any issues with this perspective? Would you recommend something different? I really don't want to refactor a bunch of the existing code, but just slip this in on top...
PS -- security is not really a concern. The only reason they have people log in is so we can track orders by a person, but no money changes hands through this website. There is also no personal information that a user can view or edit, either.
This is how I do it. I actually have a cookie that holds their login and password, this way I can automatically log them in should they not be logged in. I expire the cookie after a couple of days of inactivity. The downside is that everyone forgets their password because the only time they really have to enter their password is when they come back from extended time-off.
This is for an internal application, with the same customer demands that you have and this works ... and makes the customer happy.
One thing we may end up doing is just using Windows authenication, might actually work better in this circumstance.
That's the way I do it, but the problem with it (at least I think its a problem) is that when you store the username and password in a cookie there is not any encrypting when you add the cookie. If you look at the cookies in your browser the username and password are displayed there plain as day. Is it possible to get some kind of encrypting on the cookies you store? Or how would you handle this?
Check this blog posting out http://timmaxey.net/archive/2009/03/06/asp.net-cookie-auto-log-in.aspx basically you needs to save the cookie with a guid a series, and a token, the token, in my case, changes all the time, the series is something that is generated based on something, like the guid and id combo or whatever, then the guid is always stored with the user. There is a cookie table to stored this info etc... pretty secure, not 100%, but pretty good... Tim Maxey
I recommend using the Enterprise Library Crypto App Block to store an encrypted cookie which is nothing more than a GUID. Get the GUID, and use a session table in the database to track user info.
At the session start event, get the user info and cache it.
Using the session object is not recommend for user info because it won't work on a web farm, unless you use a database for session state.
You're basically rolling your own session state at that point, and I'm fine with that. However, I would not go the route of storing the username/password in a cookie (even if encrypted). There's no way to expire that from the server-side. You can always remove your row in the table to force a user to log in again, but if they hold the username/password they hold the keys to the kingdom.