I'm implementing custom authentication & session management system in Node.js & PostgreSQL. My goal is to implement sessions that expire after 2 weeks (if not refreshed/renewed).

OWASP and other resources suggest to store unhashed session IDs both in database and cookie. However, if those session IDs are leaked from the database, then they can be used to successfully authenticate before they expire.

I wonder if hashing sessions would add some additional security against such situations. The implementation I'm thinking about would work like this:

  1. User authenticates.
  2. A session is saved to database with id (UUID v4) and token_hash (SHA256 hash of cryptographically secure random string).
  3. Both id and original unhashed token are saved to response session cookie(s).

Then on subsequent requests:

  1. Server reads id and token from request session cookies.
  2. If there's a session found with id, then the token is verified against token_hash. If it succeeds, then the user is authenticated.

(I'm thinking about using both session id and token/token_hash because I think it will be faster to first find the session simply using id, and only then verify token against token_hash. Otherwise, the token would need to be hashed on every request to find the session, which, I assume, would be slower, even if some fast hashing function like BLAKE3 would be used.)

  • 1
    Why design a custom implementation when many proven and vetted methods (and library implementations) exist? Oct 2, 2021 at 1:01
  • 1
    @multithr3at3d there can be many reasons, e.g. 1) greater control over implementation 2) needs not supported by existing solutions 3) actually creating/maintaining those 3rd party solutions 4) learning 5) curiosity Oct 3, 2021 at 3:02
  • 1
    If your database leaks, you have bigger problems than someone using the tokens.
    – ThoriumBR
    Oct 27, 2021 at 20:56
  • 2
    I think you don't realize that hashing sessions have a performance cost that is paid on every request that uses the session token. A hashed password pays the cost only during login.
    – ThoriumBR
    Oct 29, 2021 at 13:55
  • 3
    DB leaks are frequently read-only (lots of SQLi is limited this way, as are exposed backups or clone functions, etc.). If I gain R/O access to the SE DB and it's using hashed session tokens (or JWTs or similar), I can read everything that has been written - even if it's not visible to most users anymore - but that's it. Bad but hardly catastrophic for the users; most content on SE is public anyhow, especially to privileged users. If I gain R/O access to the DB and it's got unhashed session tokens in it, I can hijack your session and post content under your name.
    – CBHacking
    Feb 25, 2022 at 11:53

3 Answers 3


To answer your question:
Yes, hashing the session ID does provide protection against the specific scenario that you are worried about. Storing and validating the hash on every request will indeed protect you against database leaks.

Considering the fact that your sessions are 2 weeks long, you can speed up the check for session ID by caching the data and then doing a DB lookup just for the hashed token. Similarly, you can have a different DB schema that can be used to speed up the query.

The comments are discussing how much you should care about this scenario. There are some valid comments but I'll leave that discussion to the comments section.


Sessions should be short

Sessions are generally short. The OWASP guidance for session length is:

  • 15 minutes for high security applications
  • 30 minutes for medium security applications
  • 1 hour for low security applications

It is also recommended that these sessions end when the user closes the browser, i.e. you should be using session cookie. Browsers know to delete these cookies when the browser is closed.

Given these constraints, storing the actual session IDs should not be an issue, as it is likely that any session IDs that are harvested by a hacker will no longer be of any use by the time they are used. That is why they are generally not hashed.

How to handle "long sessions"

That all being said, I see that you have a requirement that a user should be able to access the site again within two weeks without having to sign on again. This is a common kind of requirement, and is not usually supported literally (with a session that actually lasts two weeks). Instead, the session is allowed to expire, but the browser is issued a token which can be used to recreate the session when the user opens his browser again. For example, you could set a persistent cookie that contains the user's identifier and either encrypt it or sign it using a secret key known only to the server. You can also embed information that ties the token to the specific browser (e.g. IP address, user agent header, and browser fingerprint). And, of course, the token would include an expiration date (you should not rely on the expiration date of the cookie itself). The server validates the token and its signature and spins up a new session, restoring whatever state is necessary per requirements. To the end user, this is indistinguishable from a very long session.

If you do it this way, you do not need to do anything special to protect session Ids other than ensure they are cryptographically random and unique. Just protect (encrypt or sign) the persistent token.


I think it will time consuming since you will validate id and token on each request. In my opinion, what you could do is implement stateless JWT authorization. Implement custom claims w.r.t to user ID in JWT token and set expiration time while generating the JWT token. It will minimize compute time of auth validation.

  • 1
    In terms of compute time, JWTs are almost strictly worse than server-stored random session tokens, even if the random tokens are hashed. JWT signature validation requires a minimum of two rounds of hashing (HMAC), or much much worse if asymmetric signatures are used. What JWTs avoid is the time to hit the DB or other storage.
    – CBHacking
    Feb 25, 2022 at 11:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .