I have a website issue that I am addressing by storing an encryption key in a cookie. I want to describe my issue and my solution, and see if someone smarter about such things than I thinks this is a reasonable solution to my problem and/or if there is a better way to do it.

My website allows a subscriber's customers take an interview. When the interview is done, the website sends a report to the subscriber. Due to the nature of the interview, the folks taking the interview may take a long time answering the questions. Also, because the interview asks questions about the subject's medical history, I store their answers in session state (which Microsoft Azure claims to be HIPAA-compliant).

My problem is that some subjects apparently take longer than 90 minutes (the session timeout length) to answer a single question. When this happens then the website detects the lack of session state and tells the subject that their data has been lost.

So here's what I'm proposing to do to fix this problem once and for all. When the user starts the interview, I'll create an encryption key and store it in a cookie with an expiration time of 5 days. Each time the user supplies another answer to an interview question, I'll store all of the session info, including the cumulative answers, in a string, encrypt the string with the encryption key (which I'll read from the cookie), and store the encrypted string in the SQL Server database (which Microsoft does not claim to be HIPAA-compliant). Note that I also store the primary key in the user's cookie.

Now, if the website gets an answer from the user but there is no session state (i.e. the user let the session expire) then I should be able to use the information in the cookie to retrieve and decrypt all of the user answers and thus recreate all of the session info.

So, to recap, I'm creating a per-user encryption key and passing it back and forth over the HTTPS connection with each interview question and POSTed answer. I use the encryption key to store the session state in a database, but only for the purpose of rehydrating the session state if the user lets the session expire.

My (totally amateur) analysis of the security implications:

  1. If the SQL Database is stolen, the sensitive data (the session state blobs) is encrypted. Each blob is encrypted with a different key.
  2. If a user's connection to the interview is compromised (i.e. a man-in-the-middle attack) then only that user's encryption key can be stolen. But in this case the clear-text of the user's answers is probably also available to the attacker, so it really doesn't matter.

Any other security issues? Is the concept of encrypting session data with a key stored in a cookie (whose lifetime is much longer than that of the session) a reasonable way to reconstitute the session if it times out?


I was thinking about might happen if a user started the interview then closed the browser (leaving the cookie behind), and a second user got hold of the computer. Then Parth Shah posted an answer expressing concern for that very scenario. So here is my analysis:

There are several things the second user might do:

  1. The second user might be able to resurrect the first user's session. (IE allows you to right-click its icon and select "reopen last session".) If this worked then the second user would be able to click the interview's "go back to the previous question" button and see all of the user's questions and answers. But this scenario has nothing to do with the encryption key or the cookie; it's equivalent to looking over the first user's shoulder. As far as I know, there is nothing I can do to mitigate this scenario.

  2. The second user might find the email that contains the link the first user clicked on to start the interview. In this case, the /StartInterview "GET" action first checks to see if the user previously abandoned the interview, i.e. a valid "encryption key" cookie exists on the user's machine, and an associated encrypted "session state" blob exists in the database. If it does then the user's answers are pulled out of the encrypted blob and used to create an "interview was partially completed" report that is sent to the clinician (customer). Then the encrypted blob is deleted from the database and the cookie is removed. So, in this scenario, I go out of my way to deliver the interview results without allowing the user at the computer to see them.

  3. The interview questions are displayed by the /Interview page, whose GET action uses session state data to figure out what page of the interview the user is on and, thus, what to render in the browser. When the user POSTs back to that page, the POST action saves the answer, fiddles with the session state variables to advance to the next question, then redirects back to the /Interview GET action. Both the POST and GET actions have code that checks to see if the session has expired and, if so, if the "encryption key" cookie exists so that the session can be transparently resurrected. So... if the second user opens the web browser and navigates to the /Interview page, the GET action will see that a new session is being created and the cookie exists, and it will dutifully resume the interview where it left off. The only mitigating factor for this "attack" is that the second user need to know to manually navigate to the /Interview page.

  • Is running a silent background Ajax request violating any security practice? This way, you can keep the session alive until the user takes his 90 minutes. – AKS Apr 27 '15 at 2:46
  • Actually, I'm doing that as well. But this will fail to keep the session alive if the user walks away long enough for the PC to go to sleep, or if JS isn't enabled. The cookie hack should allow the user to actually close the browser. When the user tries to (re)start the interview, I can detect the cookie and offer to resume the interview. – Bob.at.Indigo.Health Apr 27 '15 at 4:11
  • Can you make any assumption on the modern-ness of the browsers the users will be using to complete the interviews? For example can you assume the users' browsers do support HTML5? – Parth Shah May 27 '15 at 4:00
  • @ParthShah No, I need to provide as pleasant and functional an experience as I can to the user regardless of their browser. In particular, I can't assume they support HTML5 beyond whatever magic modernizr gets me. – Bob.at.Indigo.Health May 28 '15 at 16:56
  • @Bob.at.SBS where and how do you store responses of completed interviews? Or do you just make a report immediately after it is completed, send it to your customer and delete data off your database? – Parth Shah May 29 '15 at 0:14

I'm assuming the user logs in or proves who they are, and would not be anonymous and only providing an encryption key for authentication.

It seems like it would be best to just periodically POST the answer to the server and store them in a HIPPA compliant way there. StackExchange temporarily stores your answers, so you could look and see how they are doing it.

Storing the encryption key in the browser seems unnecessarily complex, and although it does add security temporarily by storing the key in the client (i'm assuming the server stores the answer eventually), it also introduces some new potential vulnerabilities if you implement the crypto incorrectly, the authorization (tying the session with the key), or logout (clearing the cookie) incorrectly.


I am worried about multi user scenarios: multiple users access the same machine under the same account and try to access your website. If you assume any user who goes to your website and has that specific encryption key cookie stored on their machine is the user who actually submitted the data, then you can run into an issue. I am not sure how often this can happen for your specific set of users.

I would highly recommend encryption the contents of the cookie from the server side prior to sending it to the user. If you are using ASP.NET MVC, then this is as simple as

var ticket = new FormsAuthenticationTicket(...);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
Response.SetCookie(new HttpCookie("UserInterviewCookie", encryptedTicket);

Decrypting this ticket would be very easy on server side and you are definitely mitigating the risk of another user being able to see the interviewee's cookie (which exposes encryption key).

  • Thanks Parth Shah. I had been thinking about the same "multi user" issue myself, so, in response to this answer I added some more analysis to the OP. But, note that none of the scenarios I can come up with are affected by whether or not the second user has direct access to the encryption key. Knowing the key doesn't help you unless you also steal the SQL Server database, at which point you could decrypt that one user's answers. But, as I pointed out in the OP, if a man-in-the-middle could read the cookie, he could just as well see the plaintext answers. – Bob.at.Indigo.Health May 31 '15 at 16:46
  • @Bob.at.SBS I wasn't thinking along the lines of man-in-the-middle as much as a more likely another patient in the family who is also invited to do a similar survey. I don't know your authentication story really so I just brought up your attention to this risk. – Parth Shah Jun 1 '15 at 2:33

Your Answer

