views:

217

answers:

5

We are trying to decide the best decision to maintain state across our web application. We are incline to use Encrypted cookies on the browser, but some of our developers think we should go with Session variables on the server.

The main reasons why I think Cookies are a best approach is just because we will not depend on the app server in a load balance scenario.

The main reason against using cookies is the handling of the cookies could be messy.

What is your take on this topic?

EDIT 1:

Ok. I see from the first posts that neither approach is best. What will be the desire approach then?

+1  A: 

The traditional approach is Session backed by SqlSessionStateProvider.

The modern approach seems to be to use the database for storage and to use a cache (memcached) in front of the database to speed up lookups. But Session is out, as are encrypted cookies (except for the auth cookie).

Justice
Distributed Cache does seem to be the new way of things...
Chuck Conway
A: 

Yes, I suspect your handling of cookies could be messy.

I would recommend using as ASP.NET StateService, which can run on any machine, to handle the sessions.

If you go the cookie route, you do need to be very careful about how you do it, and unless you're an expert, you'll almost certainly do something wrong.

Noon Silk
Can you explain more on the cookie route?
Chuck Conway
+4  A: 

There are two issues here. First is the difference between cookies and session. Unless you are using cookieless sessions (like unique IDs in the URL), session is just a cookie with a very short expiration. You can easily configure an application to share session across multiple servers by using a state server (ScaleOut, Velocity, SQL Server)

That of course assumes you are using the user's cookie to store just a unique ID, and linking that back to all the true data on the server, probably in a database. However:

Storing sensitive data in a user's cookie, even if encrypted, is not really that secure, because it has to be decryptable, which means it is vulnerable. Any time you choose to use two-way encryption in your application, you are taking on a much heavier cryptography burden to maintain the same level of security. If you don't have some considerable cryptographic expertise at your disposal, it's probably best to take the safe route and just not do it.

So in short, use built-in session or roll your own, either way make sure the only piece of information you send to the client is an unguessable ID that you tie back to the data stored on your end.

Remembering a user with a cookie:

Assign... a temporary ID associated with that user, like a GUID. Since GUIDs are astronomically unique and practically collision-proof, they're also virtually impossible to guess or predict from outside the system.

The advantage to rolling your own cookie-based session/"remember me" functionality is it gives you more control over how long the information is persisted, distributed, etc. On the other hand, it does represent more work, some of which is re-implementing functionality that comes out-of-the-box with ASP.NET Session. Typically I recommend using what's already there unless you can clearly articulate some driving business requirement that eliminates that as an option.

Rex M
Hi Rex, thanks for your support and comments. Is there any best practice in order to implement state sessions?
Geo
Picking the correct encryption algorithm makes hacking the encryption extremely difficult. It's more likely someone will try to use the cookie in an unintended way to breach the system, but that threat exists with ANY cookie, including the auth cookie from asp.net.
Chuck Conway
@Geo sure, see the additions to my answer
Rex M
Charles: You're wrong. You can trivially mess up how the encryption works, potentially allowing someone to determine what is valid and what isn't.
Noon Silk
@silky I think you and @Charles said two different things that are both true. Picking the correct encryption algorithm does indeed protect the data well enough that attackers will direct their efforts elsewhere. It's also extremely easy to not pick the correct encryption algorithm.
Rex M
Rex: No, picking the correct algorithm is not enough; unless you mean 'algorithm' to mean something more than choosing 'AES'.
Noon Silk
+1  A: 

I don't understand why the Cookie is getting such a bad rap here. I've seen the Cookie approach used in some very large systems and I've never seen it hacked.

Chuck Conway
@Charles I don't think the cookie itself is necessarily getting a bad rap at all - simply making the argument that given two options - sending a block of sensitive encrypted data over the wire to reside on an uncontrolled system for an indefinite period of time; or *not* doing that, the latter is more secure. It removes the possibility of ever having a "whoops, we messed up our encryption", which IMO is a lot easier for the typical dev than "oops, my GUIDs are predictable."
Rex M
I agree wholeheartedly. I've never seen anything other than random GUIDs stored in cookies with something like AES applied.
Chuck Conway
@Charles I'm curious - what does encrypting the GUID accomplish?
Rex M
We asked the same question in the system I am thinking of. It wasn't until hackers figured out that the Guid was the primary key to their account and started hacking our system via the API, that it became an issue. From that point on, all data was timestamped and encrypted.
Chuck Conway
+2  A: 

From an Architecture stand point, what you should be thinking about is the expected scale of this application. And most likely, the smartest thing is to just start out with the ASP.NET built-in session functionality. Later, if you find that you're really needing it, then add either:

  1. Low to medium scalability: Load balancing with sticky sessions, or load balancing based on request IP address (& still using ASP.NET Session).
  2. Medium to high scalability: A shared in-RAM session store, i.e. shared ASP.NET StateService, project "Velocity", ScaleOut SessionServer, etc.
  3. High scalability: A home-made cookie-based session system that is completely 'stateless' between web servers, in the sense that it's based on pre-shared secrets and hashes which are validated without querying a central session store. If you go this route, then you should consider storing non-sensitive user settings in the cookie too, to scale this as well.

The benefit of the completely cookie-based session is that it is infinitely scalable. Every time we get a new user, we also get a new remote PC which can store his session state for us, for 'free'. Of course the hashing in our web frontend servers takes some CPU, but the frontend tier is stateless and easy to scale. The downside is that it's more development work.

Ask Bjørn Hansen has a overview of sessions in cookies in these presentation slides, from around slide 16 and forward. Theo Schlossnagle wrote about them in his book Scalable Internet Architectures. Here is a good scientific paper on making really secure cookies, with better security than the proposals from Ask and Theo, if memory serves me.

Note that you may not need as much scalability as you might think. As an example, Stack Overflow is served by just 2 frontend servers, with a load balancer dividing up traffic by user IP address. This makes local ASP.NET Session on each frontend webserver work as normal, as long as all webservers are operational -- a acceptable and very simple solution for most sites with 2-5 webservers.

There is one consideration that might overrule the above. If you find that you need a shared cache for other data (SQL query results, results of re-useable but very CPU expensive computations), and you're already going to implement such a cache, then it only makes sense to stick sessions into this cache too. Examples of the kind of shared cache that I'm talking about are Memcached, Microsoft project "Velocity", Shared Cache, ScaleOut StateServer and others. Many sites won't be needing this, but it is a very good solution. This solution might get more accessible in terms of price & development time once project "Velocity" is released, depending on Microsoft's intentions with "Velocity".

Conclusion

  1. Do you only need sessions shared across frontend web servers, or do you need this for other data as well (SQL results caching etc)? Do you need a shared in-RAM cache in general? If so, you'll have to look into shared caching / clustering middleware in general.
  2. If not, do you know what scale you'll be operating at? If you do, then should be able to decide which of the 4 options for session data (from ASP.NET built-in Session to cookies) fits you best.
  3. If you're just starting out and don't know how many users you will attract, then I would begin with the ASP.NET built-in session functionality, and only add more complex solutions later as the need arises.
Jesper Mortensen