Session management is an integral part of today's web applications. You receive limited support from the HTTP protocol and have to handle most of this yourself. No wonder session management vulnerabilities consistently make it to the top 3 of the “OWASP Top 10” list. This post aims to introduce you to the model of session management.
This post only covers the basics. The security of session management relies mostly on the IAAA (Identification, Authentication, Authorization, Auditing) model, which builds on session management. That is discussed in another article. Let's get the basics nailed down!
Here is the definition according to Wikipedia.
A session is a semi-permanent interactive information interchange. It is set up or established at a certain point in time, and then torn down at some later point. A session is typically, but not always, stateful, meaning that at least one of the communicating parties needs to save information about the session history to be able to communicate.
We see two important points here: lifecycle and state. Let's take a look at each one.
A session does not spawn to existence by itself. It has a very clear life cycle from its initial creation to its final destruction. The following diagram shows a commonly used lifecycle.
A typical website may start a session with a user when he visits the site for the first time. From that point on, anything the user does is done within the context of the established session. At some point, the user may decide to authenticate to reach extra functionality. Once finished, he will log out. Finally, he may choose to terminate his session altogether.
This lifecycle looks simple. The devil is in the details. The above diagram can be easily extended to include: re-authentication, session state change, idle timeout, and hard timeout. That will result in the following.
It is a bit more complex, but nothing too fancy. Idle timeout means the user will be logged out after some inactivity. Every user interaction resets the inactivity timer. Hard timeout, on the other hand, will log the user out after a certain time elapsed regardless of their activity. This is required to prevent sessions from living forever. Re-authentication is usually performed before sensitive operations like a password or email change. State change refers to an update of the session data, e.g. change the roles of the user. This is probably as far as you will ever need to go regarding HTTP session management. Let's move on.
First, we need the browser to store our session data somewhere. Depending on the implementation this can be any of the following: the cookie jar, local storage, or memory. Each has its pros and cons, but that is another post. Next, we need to be able to send the data to the server somehow. As you know, the HTTP protocol is stateless. So to handle sessions, we need to smuggle some state into the protocol. Usually, it is added as a header or a cookie. Finally, the session may also have some data associated with it which need to be stored by one of the parties.
Let's take a look at how session handling is usually implemented. First, you visit a website which gives you a unique token, called the session id. Your browser will send this piece of data back with every subsequent request uniquely identifying you to the server. Let's take a closer look.
The session id
The token given to you may be opaque or self-describing. An opaque token, in itself, holds no information. It is only used as a key to fetch the associated data server side. On the other hand, a self-describing session id is just what its name suggests: self-describing. It holds the data within the token itself. The below table shows an example of both.
|Self-describing||ZXhwOjEyMHx1c2VyX2lkOj N8c2lnOm93M2FvOGhpZg==||exp:120|user_id:3| sig:ow3ao8hif|
The opaque token is a random string with enough entropy to avoid brute-force attacks, while the self-describing one is Base64 encoded and signed to protect its integrity. Building on the idea of a self-describing token we can construct a so-called stateless session.
The statelessness, in this case, means the server does not have to store state. It can create a bunch of self-describing session ids and validate their signatures. The main advantage of this construct is its extreme scalability. There are, of course, downsides to the missing state. For instance, it is not possible to terminate these sessions on-demand. This can be solved by adding an expiration into the token itself and checking it along with the signature. This will result in the token's eventual expiry. Note, however, that one has to decide when to expire the token upon creation and this cannot be modified later. The best thing the server can do to terminate a token on-demand is asking the client to stop using it. Obviously, this raises security concerns.
Another problem with stateless-sessions is stale data. Since it is not possible to modify the token contents, nor is it possible to terminate it and issue a new one, we are stuck with potentially out-of-date data. There is a tradeoff here as well, we could issue a new token and not care about the old one, but again, this raises security questions.
Stateful (opaque) versus Stateless (self-describing)
Most of the time, security is a trade-off. When deciding which session ids to use you should consider the following: how much of the session lifecycle you want to support, and what are your security requirements? The following graphic will help you choose.
It comes down to whether you need to support idle timeout, re-authentication, immediate session data change, and on-demand logout. Implementation wise they do not differ much in complexity as there are out-of-the-box solutions available for both. As a general recommendation, you should probably go with the opaque token.
The session management model is rarely discussed. Today, we have out-of-the-box solutions available, and we suppress the desire to understand what is happening under the hood. However, knowing the model allows you to make smarter choices.
Implementations are free to choose how much of the lifecycle they implement. Be sure to know your requirements and commit accordingly.