Sharing Sessions in ASP.NET
March 27, 2013 1 Comment
In an internal work mailing list, I had a question on sharing session across multiple applications, which I assume to be web applications. It can be done … sort of. Here is the question:
The user starts an application via a browser. At that time we have session information. Now the user clicks a link within that browser that opens another application in a new browser. I want to pass the session state between the two applications.
Before getting into this, you should understand how the web works, which I detailed in a post in 2005 (which gets somewhat deep, but not all the way down to the HTTP handshake). Now for a bit of how ASP.NET works. If this goes over your head, refer to the link above.
When a request is made for a page, EVERYTHING is sent to the server. Well, not completely true during the handshake portion, but once the browser determines it has reached the correct server, it sends over the page request information, including any querystring and form arguments, and sends the cookie(s) associated with the request. There are two types of cookies sent: server cookies and user cookies (at least I think we call old style cookies user cookies).
One thing that is passed is the session token, which is how the server gets to the session object to get data for a session.
To have a second application access the session information, you have to do a couple of things. First, it has to belong to the same domain. It is not considered kosher to have www.mydomain.com/myapp1 talk to www.mydomain2.com/myapp1 talk to each other, due to cross site issues, but it is possible to have www.mydomain.com/myapp1 talk to www.mydomain.com/myapp2.
To set up the two apps, in the same domain, so you can get some session information, you have to use the same encryption keys for the server cookie. This is done by setting up the machine keys specifically in the configuration file (web.config). This is what the machine key section looks like (as a template).
<machineKey validationKey="AutoGenerate|value[,IsolateApps]" decryptionKey="AutoGenerate|value[,IsolateApps]" validation="SHA1|MD5|3DES"/>
You cannot use AutoGenerate, as each application will generate a different key. Instead, you have to create a key. So, how do you do this? The easiest way is to search Google for a machineKey generator, like the one found here: http://aspnetresources.com/tools/machineKey. It creates something like this:
<machineKey validationKey="D08D3A0822675C3B62CB539282FFD2BA596B5442D9A8CD225FCF9A9384F7680A338355EF0BB0D9A9698ECEB905508B50548670A055813EBBC391273A16154526" decryptionKey="4653D55CBBBF9D85CAFC0705D734946F007121B7A8A3EF431CDF43805F47374B" validation="SHA1" decryption="AES" />
You then use this section in all apps that need to share information. (I hope I have not forgot a step here, so I will amend this if I find I have).
The problem here is you can easily grab the session key, but not the actual session information. Why is this? Well, the session key comes from the cookie and is decrypted, but the actual session information is held not only by key, but by application. Since MyApp2 is not MyApp1, you cannot easily grab it. So, how do you solve this.
The easiest method is to store session information that might need to pass in some form of data store. In the past, when I needed this type of “single sign on”, I put it in SQL Server. You simply try to get information from session and call SQL Server (and place into session) if not found. The item(s) will not be found when you initially switch applications, so the first hit on a new application will cause a hit to SQL Server.
But the email I got this morning stated:
I have got it working using the SQL server with this solution http://www.sneal.net/blog/2007/06/27/SharingSessionBetweenWebAppsViaConfiguration.aspx , but as mentioned SQL server is not a viable solution.
Okay, so think outside the box. If you can’t use a database, what else can you use? The answer is “any other type of data store”. So, where can we store data. Here are some possibilities:
- A file. The issue here is the file has to be accessible from more than one web application, so you either have to map the same folder for both applications or lessen security slightly in IIS. The first is a configuration complexity, while the second is a potential security risk. The solution requirements will dictate if one or both of these are not workable.
- Set up a web service and let it store the session information. A bit heavier, but it has the benefit of even working cross domain as long as you can figure out a way of passing session information (which is a completely different problem).
- Use a distributed cache solution for session state and hook in various applications.
Let’s suppose the web service is used. Here is the flow:
- User logs into application 1
- Session is created in the application and the session information that needs to be shared is sent to the web service and stored there
- User does more work in application 1
- Any new information added to session is also added to the session web service
- User goes to application 2 (with some means of passing the session key)
- Application 2 checks session and finds nothing
- Application 2 calls the web service with the session key
- Information pulled from web service placed in session in Application 2
- User is able to work
There are other ways of solving this problem, of course, but the mechanism is similar with each solution. For example, Alichisoft has a product called nCache (distributed cache) which could be used as this store. I believe they also have libraries to more easily facilitate this type of scenario.
Hope this helps.
Peace and Grace,