I think, in almost all cases user preference data may be stored in a cookie with (almost) equally good results as when the User Profile API is used. Disadvantages of using cookies (for authenticated users) seem to be that a cookie can be deleted or time-out, in which case the user preference data will be lost. For anonymous users, if the preferences data needs to be persisted across sessions then a cookie will have to be used even when User Profiles are used.
So what are some of the biggest advantages/disadvanges of using either User Profiles or cookies for storing user preferences?
One of the benefits of registering on a site is that it remembers my preferences - if you're storing that information in a cookie on my machine instead of on your server then when I log into your site from another computer, I've got to set all my preferences up again - from a usability point of view, this is fairly bad.
For an anonymous user, storing the prefs in a cookie may seem fairly sensible - you don't know who they are, or whether they will comeback, and as you state, you can't work out from one session to the next who they are - however you'd probably be better off storing some sort of token in the cookie and mapping that to a preferences store on the server.
Also, I've noticed different browsers have different implementations for cookies - for example IE can now receive 50 cookies from one domain (up from the original 20), but it is still limited to a total of 4096 bytes for the entire cookie collection (and previous) - other browsers will support 4KB per cookie, rather than per domain.
Another disadvantage to holding all the preference data in cookies is that all of that data will have to be sent in every request from the client and in any response from the server whenever a change to the data is made. Whilst this may seem like a minor point in the age of broadband it is still an additional overhead. Using the Profiles API meands that the data is held at the server and only a session identification cookie needs to be sent by the browser.
Also, as you stated, for anonymous users if cookies are deleted then the user preferences held in the Profiles DB will no longer be accessible. However this will not be the case with registered users of your website. If they remove their cookies the server will still be able to retrieve their user preferences the next time they log in.
Cookies are limited in maximum length and they are using an implementation beyond of your control (after all, they are a feature of your visitors browser). Personally, I dislike relying on unknown third-party implementations I don't have any control over and if I have to, I'm trying to use it in the simplest way possible.
So from where I'm coming from, I would always store the user data on the server and just pass around a cookie pointing to that information.
Aside of not trusting the browser with a potentially big chunk of data (which may be lost, incorrectly stored or not stored at all depending on not only the browser but also, say, some antivirus application or whatever), this has various other advantages:
You are hiding your implementation from the user: If you store the data in the cookie, it's visible for anybody and can be analyzed or modified at will. This can even lead to users changing cookies to there liking and thus force you into keeping stuff around you probably want to get rid of just because some users are depending on your particular implementation at any time.
As cookies are stored in plain text, on shared machines, everybody can no longer easily see all the settings the previous user made, nor change them at will.
But the most important point remains the disconnect from not-quite-working browser implementations (just storing small tokens is the common, tested use-case)
Don't forget that one of the biggest disadvantages of using cookies is that they can be copied, so its dangerous to store authentication info on them.
I'm not familiar with User Profile API but I'm guessing it stores the information on the server(?). If thats the case then you could have a problem if you have to many users.
Overall maybe the best solution is to use User Profile if it guarantees the persistence of the information.
Keep in mind that its possible to write a ProfileProvider that persists user data in a cookie, so you can have the best of both worlds if you determine the state you want to persist is appropriate for cookies (size, security, etc).
Actually, you do not need to persist preference data in cookies for anonymous users when using the ASP.NET Profile Provider. Simply store the current UserID (which is some horrible looking session-related string) in a cookie. This becomes the previous UserID on subsequent visits, and then you can just grab the old Profile information and migrate it to the current Profile, or even authenticate them as that old anonymous Profile.
Related
I have built an ASP.Net MVC site using Forms Authentication for a client.
Recently, they have requested that an authenticated user be restricted to a single browser session. That is, if the user raises a new browser instance, or opens a new tab on the original browser window, that he/she be logged out of the original. They insist on the added security.
Does anyone know how I might approach this? Thanks in advance.
Personally, I would push back and ask exactly what security this is bringing. Maintaining state like this counter to web architecture and is only going to bring you and your users grief.
Here is what I would do if presented with this problem:
Store the username of the user in your database (i.e. LoggedOn table).
When a user logs on, check to see if their username is already present in the LoggedOn table.
If the user isn't already logged on, insert a row into the table with the username and the current time; otherwise present the user with a message informing them that they can only log into the system from one device at a time.
Include logic to expire and delete the rows in the table if a user's session expires or if the user logs out.
First a disclaimer: I'm no expert in web programming.
Perhaps you might try a system where every user interaction requires the submission of a random value that's been generated for that page (much like what's used for CSRF protection.) That key could be kept under the user's session information on the server, and if a page is ever requested without the correct key as a URL parameter, the session is invalidated. The URL from one browser won't work in another, either, since once a URL is gone to, the user's session key has changed. The only way for a user to transfer a session between tabs would be to copy the URL of an unclicked link and paste it in a new tab's address bar. Switching browsers would be even more complex assuming that ASP.Net uses a session cookie: the user would have to transfer the cookie from one browser to another. Going back would also fail, as all the links on the previous page, and the URL for the page, would carry an incorrect session key.
Also, for reference, I believe the US Gov't TreasuryDirect site works in the way you've described, though I've never looked at how they manage it.
Thanks, people for the suggestions. Each had strong merits, however I had to take a hybrid approach. I found an incredibly simple suggestion from this post.
I implemented table of active users as Karl suggested as well. This will give the client the ability of deactivating the user on demand.
Thanks again.
Think of it as one active view at a time instead of one browser or tab. Or convince the customer to view it this way.
You can always issue a unique cookie for the browser session (ASP.NET Session) and allow communication to the latest cookie issued effectively making only one session active at a time, and therefore rendering other open sessions (browsers, tabs, etc) useless with the app by disallowing them communication any longer or serving up an error page for them. To do so you have to recognize who the user is and authenticate them against your app. This is half the puzzle and will force the user down to use your app in only a single browser at a time on their machine.
The other part of the problem is to pare down the windows and tabs that are part of the same browsing session of that browser, to allow only one view to be active at a time. To do so you can issue a unique sequential ID to the viewstate of each page for postback to the server to uniquely identify that page apart from other pages sharing the same session state (whether that page be in a browser tab, a frame or new window, etc). Or a code of your choice that's traceable. You then know which page is posting back within the session and can disallow others or deactivate previous ones by, again, shutdown down communication in some manner or serving up an error page, etc.
A new browser instance or a new tab may or may not be part of the same browsing session depending on how the browser is configured. I believe, for example, IE provides a setting that allows the behaviour to be set of whether a tab opens in a new process or session or shares the session. You won't necessarily get expected consistency across browsers to rely on for this feature, therefore you need to take programming steps to reign it in, like those described above.
You can additional steps like disallowing the user to be connected from a different IP# at the same time.
I am after some advice regarding use of GUIDs from the security perspective. I have developed an ASP.Net application. It provides the user with access to some material, such as documents and photos, that aren't on the web server. These are stored on a file server. I have a 'GetResource.aspx' page which takes the ID of the resource, opens it using System.IO.FileInfo writes it to the response stream and returns it.
So, GetResource.aspx?id=123 would return, say, a picture that the user has access to. Of course, the user could manually enter the URL as GetResource.aspx?id=456 in which case the picture / document etc with that ID would be returned and it may not be one they have permission to access.
So clearly using an integer ID is not adequate. Would using a GUID as the ID provide enough 'randomness' that I could reliably assume the user could never manually enter "GetResource.aspx?guid={A guessed guid}" and ever expect to access a valid resource, including if using a script that made many random guesses per second?
Or, is there no substitute to determining the ID of the user from a Session variable, determining he does actually have access to the requested resource and only then returning it (Which as I write this I'm more and more convinced is the case!).
Thanks
There is certainly no substitute to authenticating the user and seeing if they are authorized to access the resource. What you are proposing here is a method of making it harder for a user to hit on a valid id for a document they are not authorized to view (either by mistake or on purpose).
A GUID is certainly large enough that you would never get "accidental" valid ids in practice. That makes a GUID without authorization checks a system that works great as long as noone is actively trying to break it. On the other hand, authorization checking is a system that would work great even in the presence of active attackers (of course this depends on what the attackers can manage to do).
You should choose between the two approaches depending on the nature of your application (is it public? are the users known and accountable for their actions? how bad would a "security breach" be?).
You should be determining if the user is authorised before blindly serving it if it is protected content.
The GUID does help to some extent, it makes guessing URLs harder, so I'd still recommend using them. But URLs can still be shared (even accidentally). If you are just going to serve up the content anyway regardless of who makes the request then it is of little real protection.
If you think that content is restricted one and having some personal data then you should go with username and password thing.
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!
I am working on a small web application right now and part of the requirements is to allow the user to pick how their session will be managed: with either cookies or HttpSessionState. I have researched how to use cookies (http://www.codeproject.com/Articles/31914/Beginner-s-Guide-To-ASP-NET-Cookies) and Sessions (http://msdn.microsoft.com/en-us/library/ms178581(v=vs.100).aspx). I will be using non-persistent cookies.
The application will collect some data about the user (name, age, school) and take this session data and display messages on another page depending on the data that the user entered.
The thing I am having problems with is how to deal with how the user will pick the management. That information is also part of the session! The selection will be checked on every page on the web application.
I have researched globals (http://www.dotnetperls.com/global-variables-aspnet) but that is not a good method because it can be shared among different users which is not what I want! Correct me if I am wrong. How can I store this data temporarily through the session without actually using a session or a cookie?
Is it even possible to do this with cookies and sessions being mutually exclusive?
At the end of the day, you should save it somewhere. This option if it is not persistent, as it may be asked/changed by every time user visits the web site, the easiest way is to save it in a hidden html field. As user submits the forms, the value will be passed to the next page if you are using html forms. Or you can retrieve the value and send it manually in asp.net (e.g. Transfer).
You may use ViewState (not recommended) as well. If the information should be persister for future, try using User Profiles in ASP.net and save it as a custom field in database. This one is really cumbersome.
I've recently been developing a website using asp.net webforms that uses in proc sessions and I noticed that session ids are shared amongst browser tabs. So I was wondering what you would do for the following situations:
Problem:
Multiple logins with different users in the one browser problem
User opens browser tab 1, logins
with "user1" - store in
session
User opens browser tab 2, logins with "user2" - store in session
At this stage session information is now pointing to "user2" because of how session id is shared amongst browser
tabs
User tries an action on tab 1 and suddenly they have "user2"
information
How do you alert the user in tab 1 that the user has changed or how do force tab1 user to logout?
My initial thought was to keep a list of active users with session id via database or application object, but the problem I face is that in tab 1 what am I going to compare the list against, when I do a request the HttpContext.Current.User would be updated with "user2" how do I know browser tab 1 was initially for "user1"
Appreciate anyone letting me know of any alternatives or best practices for the above problem
Regards DotnetShadow
Why don't you warn when user2 logs in instead? With a message like "You are already logged in as user1, are you sure you want to login again as another user?"
All tabs in a browser belong to the same instance, so all tabs share cookies and sessions, there isnt much you can do about it. If you want to implement this badly the only solution that comes to mind is carrying a unique session id with each URL. Based on that unique id you can link a specific user. You will need customize the session logic and would have to make sure all links in your website carry this unique id. It could be done with alot of effort but the real question is , is it worth doing?
Some have suggested adding uniquifiers into the URL, and tracking based on those.
If you're going to do this, you may as well just let ASP.Net do this for you by turning on cookieless sessions - it then uses the URL to contain the session ID.
That's just how it is. You can't do much about it. Users are now accustomed to this behavior as it is consistent among famous internet sites like gmail, etc... so it shouldn't be much of a problem to them.
What I do to avoid this problem is redirect to append a short, random in-url login-identifier.
Then, rather than use session directly, I store a strongly typed object in the session vars under the random in-url code, and use that object for session storage. If you want to keep it simple, you could use a Dictionary. In addition to the normal session timeout, you should keep track of the last usage within each login-id and manually time-out a session if it's too old to avoid new users from keeping old logins alive.
Essentially then, each ASP.NET session corresponds to any number of login sessions.
This has the following advantages:
You can log in as multiple users simultaneously. That's handy to be able to do for many sites.
In public terminals, it helps avoid accidental session hijacking. When a user leaves a public terminal, closes the webapp tab but not the browser (which is quite common) and another person then approaches that terminal and opens a new window or tab to your site, this new user sees no trace of the previously logged in user. Of course, users should log out, and anyone can inspect the history, but there's no reason to invite abuse.
CSRF attacks against your site are a little bit harder since a url without the random login-id is meaningless.
The implemenation is quite simple if you use a hashtable - after all, any sessionstate-consumer already is written to store and retrieve data from a hashtable, you just need to change the hashtable it's using and should ideally include a custom timeout.
The obvious downside is that you need to include the random code in the url; and that you need a bit of extra implementation. You might hide the extra code using an iframe and/or javascript+XHR based site, but doing so is a much more invasive change to a site. Finally, note that cookieless sessions are not the same; though they're simpler to turn on, they involve a much longer less human-friendly url token, and by lacking the normal cookie session token, also are less secure vs. session hijacking (since suddenly any other program or even machine that discovers the session ID can pretend to be that user).
How about storing the data in viewstate? That would be unique to every window.