0

What is the most secure was to generate cookies that makes it hard for a user to be able to guess the session cookie of another particular user or that will be accepted as a valid session cookie. Also, in a way that gives the server the ability to set an expiration time for it. A cookie that we cannot learn anything about it. I was thinking about using public key cryptography to encrypt the username, but then if this cookie expires, how can we generate a new one?

I know we can generate random ones, but I want a way to do this using one of the user state information. I want to create a scheme for creating and managing sessions that is suitable for multiple servers handling user sessions.

  • Try using a deterministic random bit generator for your purpose en.wikipedia.org/wiki/Pseudorandom_number_generator . In every language there are such functions. like /dev/urandom or other things where you can get such data. – CD Rohling Mar 13 at 18:47
  • One of the requirements for this session is to use the user's state to generate it. That is why I feel stuck. – Carlos Mar 13 at 18:54
  • As I allude to in my answer, this feels like an XY problem, where you're asking how to implement a solution you've come up with to a problem, but you haven't stated the actual problem. If my answer below doesn't answer this for you, you need to edit your question to state what you're actually trying to do in the first place, as right now your question is rather devoid of context. – Polynomial Mar 13 at 18:56
  • Thanks! I think it was clear. – Carlos Mar 13 at 19:01
2

The standard way to do exactly what you're attempting is a JWT (JSON Web Token), which is a structured data blob containing a cryptographic signature / MAC that can be generated by an authentication server and then verified by any of your servers (for example, only the auth server has the private key needed to create the signature, but all servers have the public key needed to verify it). JWTs are typically either stored and transmitted in a cookie, or stored in JS local (session) storage and transmitted via JS-initiated requests (think Angular, etc. using XHR or fetch) as a Bearer token in the HTTP Authorization header.

JWTs contain identity and expiration information, and usually also role / access information and potentially other data. They are not typically encrypted (just base64-encoded), so don't put any info in there you don't want the user to see. However, attackers can neither tamper with existing JWTs nor generate valid ones from scratch, as they would have no way to (re-)create a valid signature.

JWTs are a widely-used format, so there are tons of libraries that implement them. Not all of these libraries are equal in quality, though. JWTs also provide a way to authenticate and even authorize a user without consulting any server-side state (like a database); this makes them ideal for widely-distributed or heavily-scaling services.

JWTs have two major weaknesses: they are hard to revoke and they have a single point of failure for the whole system (the signing/HMAC key).

  • The revocation problem is typically handled by having the JWT lifetime be very short (a matter of minutes) and - if longer sessions are needed - also issuing the user a "refresh token" at login; this token is simply a cryptographically random string that is stored in the database server-side. When the JWT expires (or is about to expire), the client exchanges the refresh token for a new JWT; this does cause an auth database hit, but most requests are still able to verify auth statelessly. Actual revocation can be implemented by creating a cache of invalid JWTs that is pushed to all servers and that every incoming JWT is checked against, but this adds complexity and costs performance and is rarely done in practice.
  • The single point of failure is that if an attacker ever figures out the signing/HMAC key, then that attacker can forge completely arbitrary JWTs (any user, any role, won't expire until 2700, etc.) and, if done carefully, this is hard to detect (detection after-the-fact would usually require logging auth requests and user actions and noting that a user took actions without completing the auth flow, but that kind of log cross-checking usually can't be done in real-time). Compared with traditional session tokens (which are just random strings, same as a refresh token) and cannot be forged unless the attacker is able to write a value into the database or the server's auth cache, this is a somewhat greater risk and requires that the keys be very well protected, and also that it be possible to rotate the keys (which invalidates all JWTs signed with them) on-demand.
0

If I understand your question correctly, you want to implement sessions that work across multiple servers simultaneously, e.g. in a load-balanced environment. If so, I think you're going about this the wrong way.

Load balanced / multi-server sessions can be implemented at scale without requiring you to increase your risk profile by putting integrity-critical data into a cookie and thus having the potential for client-side manipulation.

The industry standard approach is to back your session data into a database (e.g. MariaDB, MSSQL) or data store (Redis, MongoDB). These solutions themselves offer scaling with consistency, so you don't have a single point of failure, and most (if not all) languages and frameworks support database backed server sessions. This allows you to have sessions be entirely independent of the server instance that the user happened to login with, and allows the session data itself to be replicated and accessible across all instances without any additional code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.