Rainbow
Rainbow

Reputation: 241

How to safely store & process secret key for JWT

After reading this: JWT: What's a good secret key, and how to store it in an Node.js/Express app?, on how to store "secret key" to assign JWT tokens. I had security questions. My data (messages, username, etc...) are going to be encrypted (in database) and only authorised users can decrypt it (based on their private key). Since JWT tokens are generated using 1 "secret key" which is stored on the server, in case an attacker gets the "secret key" and get's hold of the database - tokens can be forged and therefore data can be decrypted bypassing "password", which makes encryption pointless. To protect the "secret key", I could use these methods

Method 1

Store the "secret key" on a separate server (like HSM) which will be received during login and then used to set the token

Method 2

Encrypt some kind of salt for each user and use it as the "secret key"


I'd like to hear your thoughts and ideas. How does facebook or twitter do it? Do I really need HSM to store private keys for encryption or there's some kind of alternative (eg: safe file system) ?

Upvotes: 23

Views: 29351

Answers (2)

SilverlightFox
SilverlightFox

Reputation: 33538

Edited 2024-05-01 to clarify from comments made in stof's answer. My answer was not meant to mislead and I hope the update clarifies things.

Using JWTs or not depends on your risk appetite. Individual JWTs cannot be revoked server-side very easily so could be unsuitable for highly secure applications.

A normal session token that is checked server-side may be more suitable if you don't want any risk regarding revoked tokens being used. Yes, you can do this with JWTs (i.e. check the user account is still enabled server-side), but then you have to question the benefit of using JWTs in the first place if you don't trust the signed request.

For example, if the system issues a JWT for admin requests, and the user finds out that their account has been compromised and changes the password, their JWT will still be valid until the expiration. This could allow an attacker to continue any active sessions until the JWT expires.

If you're relying on JWTs alone for authentication and/or authorisation, then you are accepting the risk that you cannot easily revoke individual JWTs.

Of course you can revoke the certificate or the signing keys themselves, but this may be a drastic measure on a large system that could have many JWTs signed by the same mechanism. You would be executing a mass logout of users, for the benefit of the few, which could have implications, especially in a multi-tenanted architecture.

Short lived tokens can mitigate this, so if a JWT expires in say five minutes and then a refresh token (which is checked server-side) is used to get a new JWT, it can limit exposure of the system after a credentials breach or session takeover. This rolls back into my question regarding your risk appetite and what's acceptable for your system.

There is also a middle ground available here. Trust the JWT for non-sensitive requests (e.g. read only view of a profile page), but check server side against a revocation list too before any sensitive actions are taken. Tokens would get added to the revocation list upon logout, or the account being disabled, locked or deleted. This could be done by adding an ID to the claim, and the revocation list is simply a list of revoked IDs stored server-side, maybe with the date/time of revocation and the reason stored against the record. This way you have the best of both worlds. Performance, plus the extra security when required.

In addition you could have a gateway that only lets valid JWTs through to the application endpoints based on their valid signature, and any further checks such as revocation lists are implemented server-side where appropriate.

The following are comments on the original question, rather than on JWTs in general.

HSM is a good option, although you'll either need to cache the key in memory to validate every subsequent request unless you are using an asymmetric algorithm where the public key can be stored freely.

The file system may be "secure enough" given that an external attacker cannot arbitrarily access files stored on your server, although an asymmetric algorithm such as EC or RSA would be highly recommended. These also mitigate brute force attacks of the key.

Having a per user key somewhat defeats the objective of having a client-side session state mechanism as you will have to lookup this key on every request in your database.

See also Are JWTs a secure option for user authentication?

And also this question.

Upvotes: 8

Stof
Stof

Reputation: 670

@SilverlightFox answer is not correct.

  1. A JWT signature verification check should fail if the X.509 Certificate used for signing is revoked (this is described clearly on the jwt.io introduction page), so JWT tokens are actually very suitable for highly secure applications contrary to the accepted answer so the entire answer is questionable at best, misleading and very harmful at worst.

  2. A HSM can generate a securely seeded secret, so that the secret is not deterministic in any way. Outside HSM's most generated secrets (if not all) are only pseudo-random and not strong enough for some cryptographic purposes. In JWT the secret generator will be the party to read data (decipher), ergo a HSM is not meant to do that, right? A client will want the clear text data not the HSM, so the client may trust a HSM to create it's secret then the client uses that secret to then create an RSA/ECDSA private key pair for JWT use. I.e. the client creates the key pair. Because the assurance is gained when only the intended reader of the sensitive data can decipher, meaning the client must hold the private key and never share it with any other party. The client will share only a public key, so that other parties can encrypt data (encipher) in a way that only the client holding the private key can decipher. Sharing a private key is poor security practice and breaks the security model making the JWT meaningless. There is an alternative to a HSM where a private CA issues an X.509 Certificate for the purposes of generating RSA/ECDSA key pairs on the client too, but again a client must securely store this and treat it as a secret.

  3. File systems are not considered secure, even when encryption at-rest is in place (because nothing is encrypted at-rest during operation of the server ergo the server is not at-rest, everything is in clear-text during operation). There are many trivial SSRF and RCE exploits available to traverse file systems of servers, both known and unknown, even software installed with defaults often allow this or are easily misconfigured before we even consider static code vulnerabilities. A secure storage is going to require data protections, i.e. purpose built security controls to assure the data is protected, and a plain text file stored on the server has no such security characteristics unless you specifically add them. Some examples is making sure that the directory owner is not the same as any process that take user input, the sensitive file is stored in a directory inaccessible by any process that takes user input, and you are running security modules like SELinux to enforce a security policy that protects this data speifically.

  4. Having a per user key is the objective of a JWT that uses RSA/ECDSA. It precisely has 1 purpose, so you're very mistaken on this point. It only exists to encipher application data in such a way that only the client requester with the private key may access it and decipher it. Any other implementation is not following JWT, and is likely applying poor PKI practices, and lacks the 1 security characteristic it was designed to apply; confidentiality. There is another type of JWT that does not require confidentiality at all, and only requires integrity via the use of HMAC and has no encryption at all, you may be misunderstanding JWT and mixing these distinct modes of JWT to form your current understanding.

Overall, this accepted answer is highly misunderstanding fundamentals of JWT and has dangerous security advice.

Answer to the question

Since JWT tokens are generated using 1 "secret key" which is stored on the server

This is not how you first explained how you implemented JWT, you said

only authorised users can decrypt it (based on their private key)

Which is it?

As described above; generating RSA/ECDSA key pairs on the client and send the public key to a server to sign the JWT, a server should never have the private key (the secret) used by a client to decipher (decrypt) the JWT.

How does facebook or twitter do it?

They are the JWT producer in an OIDC flow, i.e. they do not sign the JWT using a private key, they sign it with a public key so the holder of the private key (the OIDC consumer) can decipher the content of the JWT.

An aside; are you solving the same use case as facebook or twitter? Are you assuring identities to other 3rd parties? are you the JWT producer for the purposes of allowing your consumers trust an identity you validated? if so, you should never ever ever and i stress never know the private key of the consumers, you only need o sign the JWT with a public key provided to you.

tokens can be forged

A JWT is a token that represents a claim, it claims to be authorisation but it is not actually authorisation until verified. ergo "claims". Also JWT forgery is a strange concept, is it 'forgery" when signing JWT content is done using a public key? You may be misunderstanding the JWT modes here. There are JWTs signed using a shred-secret that produce a HMAC and both producer and consumer require the same shared-secret to reproduce a matching HMAC at both ends. This is not encryption using private and public keys, JWT has variations where a HMAc can be used and the shared-secret is in fact sensitive and if exposed can be used to forge a HMAC, but the question you asked is ot clear if you are using HMAC-style JWT or the encryption-style (RSA/ECDSA) JWT the accepted answer assumed you are using.

Further assistance

Readers and past participants; There's quite a lot to learn in the above answer, I encourage you to research more about JWT, ECDSA, RSA, HMAC, OWASP key management, Cryptography storage cheatsheet, and SAMM's secrets management.

Then ask more question in this community for more specific issues you come across.

Upvotes: 22

Related Questions