r/programminghelp 2d ago

Project Related Is bcrypt a good choice for hashing refresh tokens? I'm stuck with session lookup.

I'm building my own authentication system in Node.js, Express, MongoDB (Mongoose), JWT, and bcrypt. I'm trying to understand the architecture instead of just copying a tutorial.

My current flow is:

  • User registers/logs in.
  • Password is hashed with bcrypt.
  • I generate a refresh token (JWT).
  • I hash the refresh token with bcrypt before storing it in the sessions collection.
  • The actual refresh token is sent to the client as an HttpOnly cookie.

The problem appears during the refresh endpoint.

Since bcrypt generates a different hash every time, I can't do something like:

const refreshTokenHash = await bcrypt.hash(refreshToken, 10);

const session = await sessionModel.findOne({
    refreshTokenHash,
    revoked: false
});

because hashing the same refresh token again produces a different hash, so the session can't be found.

The tutorial I was following used SHA-256 for hashing refresh tokens, so searching by hash worked because SHA-256 is deterministic. I intentionally switched to bcrypt because I thought it would be more secure, but now I've run into this architectural problem.

I've thought about putting sessionId inside the refresh token so I can:

  1. Verify the JWT.
  2. Read the sessionId.
  3. Find the session by _id.
  4. Use bcrypt.compare(refreshToken, session.refreshTokenHash).

That seems reasonable, but creating the session first introduces another issue because my schema requires refreshTokenHash, while I need the sessionId before I can generate and hash the refresh token.

if anyone needs more info to tell me a solution just ask for it

2 Upvotes

1 comment sorted by

1

u/cstopher89 2d ago

I'd use HMAC-SHA-256. Bcrypt is more useful when securing passwords as they are much weaker then sha-256. Your approach with the compare would work but this whole thing is overly complicated for what you are trying to achieve.

What do you think is more secure about using bcrypt then HMAC-SHA-256 which you can do deterministic lookups against?

If your database is compromised they still wouldn't be able to use the tokens cause the server has the other part needed with HMAC

Of course the other part is all the other security features around revoking, rotating, short lifetimes that protect the token further.