Sitemap

Difference between Session Cookies vs. JWT (JSON Web Tokens), for session management.

7 min readSep 14, 2021

“Http” is a “stateless” protocol, in that every http call made to a server is like a fresh call, with no memory or “state” of the previous calls.

In applications we generally need to maintain login “sessions”, so that once a user logs in, they can continue to access different parts of the application without having to log in (i.e. authenticate) again and again for each subsequent “http” requests made to the server.

There are primarily two different approaches to session management,

  • Session or Cookies based approach
  • JWT (JSON Web Tokens) based approach

These two approaches are fundamentally distinct and fully complete for session management. In the following post we shall compare and contrast both approaches,

Session Cookies vs. JSON Web tokens — The Approach

1. After successful authentication, (in case of session-cookie approach) the server generates a “cookie”, OR (in case of JWT approach) the server generates an “accessToken”

Once the user is “authenticated” i.e. the server verifies that the username/password matches with one the userDB,

Session Cookie based approach:

1. Server generates a "sessionId" (signs it using "secret key"), and 
(a) saves the sessionId in a sessionDB, and
(b) sends a cookie with the sessionId to the browser (client side).
2. The browser (client side) receives the "cookie" in the response from server, and saves it in the "cookie" storage. 3. The browser then includes the "cookie" within every subsequent request to the server.

JWT JSON Web Token approach:

1. Server generates an "accessToken", encrypting the "userId" and "expiresIn", with the ACCESS_TOKEN_SECRET, 
and sends the "accessToken" to the browser (client side).
2. The browser (client side) receives the "accessToken" and saves it on the client side.3. The "accessToken" is included in every subsequent request to the server.

Note:

  • In case of the JWT approach, the accessToken itself contains the encrypted “userId”, and the accessToken is not saved within any sessionDB.
    Since no DB is required in case of the “jwt approach”, it is sometimes called “stateless” approach to managing sessions, since no “state” or “session” is saved within a DB (it is contained within the JWT token itself).
    The JWT tokens are sometimes referred to as “Bearer Tokens” since all the information about the user i.e. “bearer” is contained within the token.
  • In case of the session cookie based approach, the sessionId does not contain any userId information, but is a random string generated and signed by the “secret key”.
    The sessionId is then saved within a sessionDB. The sessionDB is a database table that maps “sessionId” < — -> “userId”.
    Since sessionIds are stored in a sessionDB, the “session cookie approach” is sometimes called “stateful” approach to managing sessions, since the “state” or “session” is saved within a DB.

Additional Note:

  • In both approaches the client side must securely save the “cookie” or the “jwt token”. The main difference is that in case of the JWT approach the server does not need to maintain a DB of sessionId for lookup.

In Node JS, the following libraries can be used to implement the above,

  • Cookie ← using express-session (sessionId string generated by server, and corresponding sessionId saved on server) i.e.
app.use( session ({ secret: “secret key”}) )
// a sessionId is created by "express-session" and sent in the response as a set-cookie.
// this sessionId can be stored on the server side to a DB eg. MongoDB or Redis or SQL etc.
NOTE: the "secret key" is used to sign the sessionId to verify its integrity when the cookie (sessionId) is returned back to the server on subsequent requests.
  • JWT ← using jsonwebtoken (userId encrypted within the JWT token) i.e.
const accessToken = 
jwt.sign( {userId}, ACCESS_TOKEN_SECRET, {expiresIn: “15m”} )
// Note that the "accessToken" is NOT stored on any server side DB, since there is no need to do so.

2. To maintain sessions, each subsequent request to the server (in case of session-cookie approach) should include the “cookie (sessionId)”, OR (in case of JWT approach) should include the “accessToken”

Now that the user is authenticated (and the client side either has a “cookie” OR has an “accessToken”), let’s say the logged in user wants to perform a bunch of actions like adding items to a shopping cart.

For each request made to the server, the server does the following

Steps in Session Cookie based approach,

1. Get the "sessionId" from the request "cookie".2. Verify the "sessionId" integrity using the "secret key". 
Then look up the "sessionId" within the sessionDB on the server and get the "userId".
3. Look up the "userId" within the shoppingCartDB to add items to cart for that userId, or display cart info for that userId.

Steps in JWT based approach,

1. Get the "accessToken" from the request "header".2. Decrypt the "accessToken" i.e the JWT, using ACCESS_TOKEN_SECRET and get the "userId" ---> (there is no DB lookup).3. Look up the "userId" within the shoppingCartDB to add items to cart for that userId, or display cart info for that userId.

So notice that in case of the session cookie approach, the server would need to maintain a list of all the sessions in a sessions DB. Also notice that this means that there would be a DB lookup to get the userId . DB look ups are relatively slower than JWT decrypting action.

In case of JWT approach, since the JWT token itself contains the (encrypted) userId info, we do not need to perform a “look up” to get the userId. The moment the server decrypts the JWT token, it will get the userId.
(NOTE: only the servers that have the shared ACCESS_TOKEN_SECRET can decrypt the JWT token).

This allows for multiple servers to be scaled up separately and without the need to have a current copy of the sessionId DB on all servers, or have all servers access a common sessionDB.

As long as a server has the same ACCESS_TOKEN_SECRET that was used to generate the JWT token, that server can decrypt the JWT token and get the userId.

In Node JS, the above can be implemented as follows,

  • Cookie ← using express-session
app.get("/", (req, res) => {
console.log(req.session.id) // get sessionId
console.log(req.session.cookie) // get cookie
})
// "express-session" attaches a "session" object the "req"
NOTE:
To get the userId, the "session.id" needs to be parsed thru the sessionDB (i.e. sessionStore: Mongo or SQL or Redis), to get the associated "userId".
  • JWT ← using jsonwebtoken
jwt.verify( accessToken, ACCESS_TOKEN_SECRET, (err, user) => { if (err) console.log(err) // eg. invalid token, or expired tokenreq.user = user})// jwt.verify decrypts the accessToken using the ACCESS_TOKEN_SECRET// the decrypted "user" can be saved in "req.user" to get "req.user.name" or "req.user.email"NOTE:
Once the "accessToken" is decrypted successfully, the "user" is obtained directly, and there is no separate DB lookup.

Session Cookies vs. JSON Web tokens — Advantages and Disadvantages

Session Cookies approach:

Advantages

  • On logout, since the sessionId is removed from the database, we have a precision logout i.e. logout occurs at the moment the sessionId is removed from the sessionDB

Disadvantages

  • Needs an additional DB lookup within the sessionId table to get the userId, DB look ups are relatively slower than JWT decrypting action.
  • Individual servers cannot be scaled separately since they would need to share the sessionDB.

JWT (JSON Web token) approach:

Advantages

  • Since userId is got by decrypting the JWT token, no DB call is required to get userId, so somewhat faster that session approach.
  • Servers can be scaled separately, without the need share sessionDB. This makes the JWT approach a great option for micro-services architecture.
  • The same token can be used to authenticate on different servers (as long as server has the access_token_secret), without the need to share sessionDB,
  • This also allows for a completely separate authentication server, that can be solely responsible to issue “accessTokens” and “refreshTokens”.

Disadvantages

  • Since JWT tokens cannot be “invalidated” (without maintaining them in a shared db), in JWT approach the logout length precision is set by the expiration length of the access_token. However the “access_token” lifespan can be kept short (typically 10 to 15 mins), so that tokens are automatically “invalidated” after the duration.
  • Anti-pattern: Sometimes additional and unnecessary information is stored in the JWT. The JWT token should primarily contain user information, and the data authorized to be accessed by that user should be provisioned and managed as a separate service on that respective server.

Afterthought

Combining both approaches?

Some programmers have attempted to combine the Session Cookie based and JWT based approach, and use one for authentication and the other for looking up authorized resources.

Session based or JWT based approaches are complete in themselves to effectively manage session management individually, and there is no clear advantage in combining them together (unless there is a specific use case that this solves).

And that’s it!

Session management can be implemented either using the “Session-Cookie” based approach (and is still used in many web applications), or can be implemented using the JWT approach (which is a newer approach, and is frequently used in mobile and web apps). Have fun as you develop your own awesome code, or work as part of a larger development team!.

Happy Coding!!

Found this post helpful? Hit the 👏 👏 👏 button a few times to show how much you liked it! 🙂

Follow me on Medium for the latest updates and posts!

--

--

Prashant Ram
Prashant Ram

Written by Prashant Ram

Technologist, Author, Speaker-with a passion for learning new things every day. Specializing in helping Startups and Enterprises move to the modern web!

Responses (8)