ASP.Net - What is current best practice for tracking state and session variables? - asp.net

We're creating a new consumer/public-facing ASP.Net web app. There are two concerns:
--Use cookie or cookieless forms authentication?
--If we decide not to use cookies at all, how would you store the data that would otherwise be stored in the cookie (Customer ID, AffiliateID, etc.). Does the ASP.Net authentication framework track something like CustomerID?

For a normal web app there is no good reason to use cookieless authentication - Fear of cookies died out about a decade ago.
For actual data, the session object is generally a better choice than individual cookies - The session cookie is a single value that effectively gives you a key to whatever session data you have stored on the server. There are certain specialized cases where there are problems with using session, for example in multi-server deployments, but in for most applications it is simple and adequate.
The standard forms authentication system does track the username - generally this is enough to look up whatever data you need from your database if you don't want to keep anything in the session.

If you're doing authentication, cookies are the usual method. It's very rare these days that people will have cookies turned off because so many sites already depend on them.
Having said that, ASP.NET does support "cookieless" authentication. Basically it just adds the authentication token as a parameter on the URL. It parses all outbound URLs to ensure that they also include the token information. Personally, I wouldn't bother with this and just go with requiring cookies. There are a few additional headaches when trying to go cookieless (for example, it can make SEO that much harder, because the search engines will see a different URL every time it crawls the page).

Related

What are the pros and cons of using session variables to manage a users session data?

Using ASP.NET I have always used session variables to maintain a users session data.
Typically: (Coded as simple bools/ints with around 12 total variables)
User information.
Page security permissions.
I have read increasing information regarding the negative effects of using session variables.
I am aware that session variables are stored in memory and the negative effects that using too many can have; this is not the desired scope of this question.
What I would like to know:
Using current development languages and features:
Do session variables pose a security risk?
(By security risk I mean is it possible to read / alter variables)
Is there better performance using querystrings, viewstate, caching, or making database request on every page load?
What is "considered" good practice for handling a users session data. (All topics relating to this subject are now very old and perhaps no longer relevant)?
A performance is always something subjective and may vary depending on different things. In your case you're trying to compare incomparable because
querystrings cannot be used to share sensitive user information or page security, because everyone can modify urls directly in the browser
viewstate is set and maintained on the page level. It cannot be carried across different page requests, only on postbacks of the current page.
caching is done on the application level, and all users can access it. It might work in case of page security permissions but not applicable to store individual user information.
Making database requests is the only comparable option and yes, it's slower than a session. This is where you can try to play with viewstate and caching and try improve performance and reduce a database workload.
Sessions are stored in a memory on the server but depend on cookies and in theory, it's possible to hijack the session by stealing the asp.net session cookie.
SessionID values are sent in clear text. A malicious user could get
access to the session of another user by obtaining the SessionID value
and including it in requests to the server. If you are storing
sensitive information in session state, it is recommended that you use
SSL to encrypt any communication between the browser and server that
includes the SessionID value.
Quote: http://msdn.microsoft.com/en-us/library/ms178581.aspx
Bottom line: using sessions is secure but to make it more secure use HTTPS
ASP.NET provides out of the box functionality for user authentication, role based authorization and user profiles which might make sense to use. Read more about profiles: How to use Profile in ASP.NET? and Regarding Profile and session in asp.net There is a lot of other topics and answers here on this site regarding authentication and authorization.
Do session variables pose a security risk? (By security risk I mean is it possible to read / alter variables)
Although, as smirnov quoted, a malicious user might get accrss to another user's session by hijacking the session itself, the session variables themselves are stored at server-side, and cannot be accessed directly.
Is there better performance using querystrings, viewstate, caching, or
making database request on every page load?
As smirnov wrote, the comparison isn't exactly valid. However, consider:
querystrings and viewstate are stored in the http request, therefore are both less secure and consume no memory. However, they will take some minor processing power to parse.
Caching (in the web-server RAM) the results of previous database request will lighten the load on the database and the network connections between your web-server and the DB server, and will also retrieve the data faster. However, they will obviously use more RAM on the web-server itself.
What is "considered" good practice for handling a users session data.
(All topics relating to this subject are now very old and perhaps no
longer relevant)?
Since the principles haven't changed much, the existing sources, IMHO should still be relevant.
Note: If you're using multiple servers, you'll need to synchronize the session data across them, by using a state-server, for example, or use "sticky sessions", in which each session is always served by the same server.
In my opinion you should avoid sessions as much as possible. Here are my reasons in no particular order.
Sessions doesn't scale automatically when you add more nodes (Sure you can use a dedicated session-server but that comes with some overhead)
When you have enabled sessions each user can only make a single request at the same time. Asp.net implements per user locking if the session is enabled to avoid any race conditions. This is mostly a problem in if you use a lot of ajax.
If you have to restart the webserver the user lose their session. This is really the main point for me. It really sucks to have a system where people risk to get kicked out, get a corrupted session or simply lose progress because you need to deploy a bugfix. Avoiding session as much as possible gives you much more freedom and a better experience for your user.
It's up to you but I always try to either store the data in a persistent store or use something that actually exist in the web (cookies, querystring, writing state to a hidden field etc etc). I bet there are situations where I would use sessions but my default choice is to avoid them.
These days there are more options:
Local Storage / Session Storage / Page Javascript Variable - are good for client-side storage situations. see https://www.w3schools.com/html/html5_webstorage.asp. But they wouldn't be suitable for most trust situations, not without server-side signing. A javascript variable will be lost upon page restart, but persist in browser Session Storage if it was written there. If that browser tab is closed, the Session Storage is lost, but persist in the Local Storage if it was written there.
JSON Web Tokens (JWT) - are the emerging new standard for replacing Sessions. This is a standard for authentication, roles, data, and claims, which is signed by the server, and can also be encrypted to the client can't read any of the details. This is usually stored in Local Storage by the client, and only really works for Single Page Applications which can write to the Bearer header. Don't use this for MVC (MVC.Controller) with server-side generation of HTML. JWTs can be a pain to set up and customise - the API for OWIN is terribly sparse. JWTs can get big too, which means you're always "uploading" the JWT data upon each Request to the web-server. But JWTs enable your security to be handled by one server (even an externally trusted server).
ASP.Net Server-Side Sessions - Can be in-memory in-proc, in-memory external-proc, and database.
Answering your specific questions:
Security risk - Not really. The session uses a key that's long enough that it can't be guessed. It's typical to use HTTPS these days, so that value is securely transmitted. The variables are stored only on the server, with a set per user. If a user's device is compromised, it's possible to steal the session key, but if their device is compromised, there are bigger problems to deal with.
Performance is not better or worse for "query strings", "view state", or "caching" compared to In-Proc (Memory) sessions. They're all in the realms of speed of memory (RAM) - nanoseconds. Database (disk stored) is certainly slower, because the medium access time is slower - milliseconds
Sessions are good practice. Some would recommend having a dedicated class for reading and storing each variable (using Properties), so you don't get the session variable names (strings) confused.
I am a fan of a possible hybrid approach to Sessions. see How can I store Session information in a hybrid (Database + Memory) way?

Session Authentication equivalent to FormsAuthentication?

I'm using a login form to authenticate users.
FormsAuthentication is right out as it stores sensitive user/role membership in either client-side in a cookie or within the URL. Within the URL is a huge security risk, so I won't even get into that. With the
FormsAuthentication cookie, this creates problems with a) security where the client is in the position of dictating it's own roles; and b) way too much data stored in cookies. Since I'm gaining nothing through security and loosing out big time on the size of user data storage, I'd rather just work with Sessions.
I'd like to reuse something like FormsAuthentication for all its basic login form-handling features. But i would rather have it store user data server-side in perhaps Session rather than client-side all stuffed into a single cookie. I'd rather just authenticate against a Session token of some sort.
I have no database and local disk storage of user data is forbidden. I rely on a 3rd party authentication service provider, and a requirement is that I must reduce chatter with this service. Thus, sessions for temporary storage of user info. Sucks, but that's not necessarily the problem I'm asking about. Also, a requirement is that I must set/use HttpContext.user and likely Thread.CurrentPrincipal for use later on in such things as AuthorizeAttribute, for displaying user info in views, etc.
So FormsAuthentication stores all user data client-side in a cookie. Whereas Session stores all data server-side and just relies on a simple client-side token cookie. However, Session is not available anywhere during the asp.net startup and authentication steps. Is there an equivalent forms "membership" provider that stores all data in Session server-side instead of client-side?
If there is no Session equivalent...
Where do I set HttpContext.user and Thread.CurrentPrincipal to make both values available throughout the rest of both MVC apps without interfering or messing up other MVC components?
Hinging on #1, is Session available at that entry point? If not, how do I make it available so I can create the Principle/Identity object using the data stored in Session?
This can't possibly be a unique requirement. Are there libraries already available which handle this?
Session stores information in a client-side cookie too! (or in the URL if cookieless).
If you want to authenticate a client, he'll have to provide some kind of credentials - usually an encrypted token in a cookie once he has logged on. If not a cookie, then what do you propose?
You should use FormsAuthentication. The sensitive information stored in a client-side cookie is encrypted using a key that should only be known to the web server. "the encryption methods being public knowledge" doesn't mean that you can decrypt the data without access to the appropriate cryptographic key.
You mention "roles" and a "third-party authentication provider". If your third party is also providing roles (i.e. an "authorization provider" as well as an "authentication provider"), then it would be reasonable to cache roles obtained from the provider on the server. Session is not available when a request is being authorized, so the best solution is to use the Cache (System.Web.Caching.Cache).
Personally I would encapsulate this in a custom RoleProvider. The custom RoleProvider would implement GetRolesForUser by getting roles from the third party on the first call, then caching them in Cache.
Not sure if I like what I'm about to suggest, but you could do the following:
Leverage the Application State or System.Cache as a global storage for user credentials.
Use an InMemory database (like RavenDb) which can also have encryption (in memory, I believe).
Using the Application state as a place to storage relatively common / frequent stuff I think is not a great place because of
Scaling / locking issues? <-- just a gut feeling.
Permenant data? so you have users in the website's memory .. then the website crashes or recycles, etc... what happens now to that data?
RavenDb is awesomeballs - go.use.it.now.
I understand that you are not storing anything locally, so whenever a user hits your system, you need to refresh your inmemory cache, etc. Fine. A pain in the f'ing butt , but fine none-the-less. (EDIT: unless the data has been cached in memory .. that is)
Anywys, two suggestions.
ProTip:
Oh! move away from role based shiz and start using Claims based identity stuff. Yes, it still works with IPrincipal and HttpContext.User, etc. So all previous code is NOT busted. But now it's baked into .NET 4.5
Awesome Video on this for you, me, everyone!
Finally - bonus suggestion
A nice package that auth's with either Facebook/Google/Twitter. You said you're keeping the user cred's on another site (good move!). If you're using other providers, then stick with DNOA or SS.
GL!

How important are cookieless sessions? Should a web application framework provide support for them?

We are programming a new web application framework (Second WAF). I was wondering if we should support cookieless sessions or not.
Who use it and who needs it?
I was wondering if we should support
cookieless sessions or not.
I think this depends largely on your userbase. In my organization we support several intranet applications. We also control our users desktops. Since we control their desktop environment we can control browser settings and ensure cookies are enabled. Because of this and the increased risk of session hijacking, there is no reason for us to ever allow cookieless sessions.
Who use it and who needs it?
Those who need to support sessions regardless of the end users' browser settings would need to implement cookieless sessions; keeping in mind the implications of doing so.
It is a good feature, but several aspects have to be taken into account
what if an URL containing session ID is cached by a web spider such as Google, will you be able to provide content if the ID in session is other than the ID provided in URL
security. If you don't implement it smart enough, users will be able to send a URL to another user, where the URL contains the session ID and hence, allowing hijacking the first user's session. For instance, in ASP.Net1.1 the cookieless session mechanism was considered vulnerable

How does ASP.NET (or any web framework) implement persistent session state?

For various reasons I am fed up with ASP.NET session state and I'm trying to do it myself (separate question coming soon related to why I'm fed up and whether it's feasible to do it myself, but for now let's assume that it is).
Security concerns aside, it seems like tracking sessions involves little more than storing a cookie with a guid and associating that guid with a small "sessions" table in the database, which is keyed on the guid and contains a small number of fields to track timeout and to link to the primary key in the user's table, for those sessions that are linked to registered users.
But I'm stuck on a detail with the cookie, in the case the user's browser is not set to accept cookies. It seems to me that each time a user accesses any page that has session state enabled, ASP.NET must determine whether the browser supports cookies. If there already is a session cookie sent with the request, obviously it knows cookies are accepted.
If not, it seems like it needs to check, which as I understand it involves trying to write a cookie and redirecting to a page that tries to read the cookie. So it seems, when a user with cookies turned off visits several pages of a site, that ASP.NET
(a) has to do this round-trip test for every page the user visits, or
(b) has to assume the browser accepts cookies and create a record with a (provisional) session id for the user on each page -- and if session state is supposed to be persistent, it seems it has to write that initial session id to the database on each page.
But (a) sounds crazy and (b) sounds crazy also, since we would quickly accumulate session ids for all these single-page sessions. So I'm thinking there must be some other trick/heuristic that is used to know when to do the round-trip test and/or when to actually create a record for the session.
Am I wrong to be perplexed?
(To be clear, I'm not talking about implementing a custom storage solution within ASP.NET's pluggable session state system. I'm talking about skipping ASP.NET's session state system entirely. My question is a more detailed version of this one: Implementing own Session Management in ASP.NET.)
Session behaviour is set through the sessionState element in web.config. In the sessionState element the HttpCookieMode can be set to one of UseUri, UseCookies, AutoDetect, UseDeviceProfile.
UseUri and UseCookies tell ASP.NET explicitly how to handle storing the session identifier. If UseDeviceProfile is used then the behavior is determined by whether the user agent supports cookies (not whether they are enabled or not).
AutoDetect is the interesting case that you are interested in. How ASP.NET is handling the auto detection is explained in Understand How the ASP.NET Cookieless Feature Works. In that article you will see that they have 5 different checks they do. One of the checks is, as you mention, to set a cookie and do a redirect to see if the cookie exists. If the cookie exists, then the browser supports cookies and the sessionID cookie is set. However, this is not done on every request because another check they do before tring to redirect is is check to for the existence of any cookies. Since after the initial set-cookie and redirect the sessionID cookie will be set then the existence of the cookie lets ASP.NET know that cookies are supported and no further set-cookie and redirects are required.
Well, cookies are a standard mechanism of web authentication. Do you have any reason at all why you wouldn't want to use them? Are you sure you're not trying to invent a problem where there isn't any problem?
Most serious websites I know of require the browser to accept cookies in order for the user to be authenticated. It's safe to assume that every modern browser supports them.
There's an interesting article about cookieless ASP.NET that you should read.
EDIT:
#o.k.w: By default the session state is kept by ASP.NET in-process (read: in memory). Unless told explicitly by the configuration to store the session in the database (SQL Server is supported out-of-the-box), this won't result in a database hit. The stale session states will get purged from the in-process storage. Unfortunately, with default ASP.NET settings every cookieless request will result in a new session being created.
Here's a detailed comparison of available session storage options: http://msdn.microsoft.com/en-us/library/ms178586.aspx.

User roles - why not store in session?

I'm porting an ASP.NET application to MVC and need to store two items relating to an authenitcated user: a list of roles and a list of visible item IDs, to determine what the user can or cannot see.
We've used WSE with a web service in the past and this made things unbelievably complex and impossible to debug properly. Now we're ditching the web service I was looking foward to drastically simplifying the solution simply to store these things in the session. A colleague suggested using the roles and membership providers but on looking into this I've found a number of problems:
a) It suffers from similar but different problems to WSE in that it has to be used in a very constrained way maing it tricky even to write tests;
b) The only caching option for the RolesProvider is based on cookies which we've rejected on security grounds;
c) It introduces no end of complications and extra unwanted baggage;
All we want to do, in a nutshell, is store two string variables in a user's session or something equivalent in a secure way and refer to them when we need to. What seems to be a ten minute job has so far taken several days of investigation and to compound the problem we have now discovered that session IDs can apparently be faked, see
http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/
I'm left thinking there is no easy way to do this very simple job, but I find that impossible to believe.
Could anyone:
a) provide simple information on how to make ASP.NET MVC sessions secure as I always believed they were?
b) suggest another simple way to store these two string variables for a logged in user's roles etc. without having to replace one complex nightmare with another as described above?
Thank you.
Storing the user's role information in a server-side session is safe providing a session cannot be hijacked. Restating this more broadly, it does not matter where user role info is stored if an authenticated session is hijacked.
I advise not putting too much faith in the article you linked to, but the 2002 vintage report linked to from your link is of interest. Here are my take-aways:
Don't accept session IDs embedded in URLs.
Focus your time on eliminating cross site scripting dangers i.e. scan all user supplied data and parse out executable java script.
Issue cookies for complete domains (e.g. myapp.mydomain.com)
Host your domain at a high class DNS operator e.g. one that only allows DNS changes from a preset remote IP address.
Don't issue persistent session cookies.
Reissue a session cookie if someone arrives at a login page with a sessionID already associated with an authenticated session.
Better still, always issue a new session cookie on successful authentication and abandon the prior session. (Can this be configured in IIS?)
The only way to make a secure cinnection is to use SSL. Anything less than that, and you simply have to make the evaluation when it's "safe enough".
A session variable works fine for storing a value, with the exception that the web server may be recycled now and then, which will cause the session to be lost. When that happens you would have to re-authenticate the user and set the session variable again.
The session variable itself is completely safe in the sense that it never leaves the server unless you specifically copy it to a response.
Have you considered setting up a custom Authorize tag in MVC. I gave an example of this in another question.
On initial authorization (sign-in screen or session start) you could seed a session value with the IP address also. Then in your custom authorization, you could also verify that IP's still match up as well. This will help make sure that someone isn't 'stealing' the person's session. Everytime you access your session data just make sure to pass the requester's IP and have some check on it.
Are you trying to control the access to functions at the client level? That is the only reason I would expose the roles and items to control client side functions.
Alternatively, you could create a function to obtain the items that the roles of the user are allowed to use, and then even if the function is called outside of the items given back to the web application, you can prevent the user from accessing them.
4Guys seems to show how to control functions with the roles.
The approach I have used in the past is to use symmetric encryption of a cookie alongside SSL. Encrypt the user information in the reponse and decrypt it in the request. I'm not claiming this is foolproof or 100% secure and I wouldn't want to do this on a banking application, but it is good enough for many purposes.
The main issue with session variables is that if you store them inProc rather than persisting them, then you need to apply 'sticky' sessions to your load balancing in a web farm environment. Guffa is correct that without this persistence session variables will occasionally be lost causing a poor user experience.
Sticky sessions can lead to uneven load balancing, perhaps reducing the value of being able to scale out.
If you are going to be be persisting the sessions so they can be accessed by all servers in your web farm, you may be better off using a Guid to identify the user, encrypting this in a cookie and retrieving the user record from your data store each time.
My obvious question is that why do you want to store a users role in session ?
Here is my answer to your query, how this helps. I have attached a small demo application for you to take a look at and understand my points. When you open this project in visual studio, click on the project tab on the top and select asp.net configuration. From the page that will show up you can do the user administration stuff.
You need to store the roles of a user in some secure manner ? The answer to this question is that there is no need for you to worry about storing the role for any user, when we have the asp.net membership, profiles and roles framework to help us out on this. All you need to do is create a role in the aspnet database and assign that role to the user.
Next you want to store two string in some secure manner. I suggest you user profile for storing user specific information. This way you have the information available to you where ever you want from the profilecommon class.
Also please see the attached demo application placed at the end of my blog http://blogs.bootcampedu.com/blog/post/Reply-to-httpstackoverflowcomquestions1672007user-roles-why-not-store-in-session.aspx
Just a suggestion, you might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It has a server side implementation of the cookie whereby all cookies can be stored on the server while asp.net authentification is used to identify the user. It supports encryption and is also very flexible making it very easy to switch from one storage type to another.

Resources