4

After reading this: https://stackoverflow.com/questions/30089604/jwt-whats-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. With this in mind here are my ideas

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"


My login system/authorisation gives access to pretty much all of the data, including encrypted messages, etc... So I need it to be secure.

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) ?

Thanks :)

2
  • refer to this stackoverflow.com/questions/37972285/… Jul 30, 2016 at 7:30
  • The HSM can generate a securely generated secret, so the secret is not deterministic in any way. outside HSM most secrets (if not all) are only pseudo-random and not strong enough for some cryptographic purpose. in JWT the secret generator will be the party to read data, i bet a HSM is not meant to do that.. but a client will, so the client may trust a HSM to create it's secret to then create an RSA/ECDSA private key pair for JWT use
    – Stof
    Nov 21, 2021 at 5:42

1 Answer 1

1

Accepted linked answer is invalid

The linked accepted answer in the question's comment was not very useful for information security purposes, it may have been answered by a software developer who hasn't implemented JWT or researched much themselves but instead as a software developer that used a JWT one time and clearly doesn't understand the security characteristics of JWT at all.

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 answer and the entire answer is questionable at best, misleading and very harmful at worst.

Your confusing question

This question is asked in a way that also isn't clear about operating a JWT producer, or if it is asking about secret storage of a JWT consumer - two very distinct questions being mixed into one incoherent question.

@user6227254 if you're in control of how JWT are generated, and in control of where the JWT are consumed AND this is a simple software stack with only your servers and your clients making requests - then perhaps the JWT implementation is not fit for purpose in such a straight forward stack

What are the use cases for JWT?

JWT in OIDC (OpenID Connect)

The typical use case is something like OIDC (OpenID Connect) where the OIDC producer will generate a JWT for a response to a client OIDC consumer that is establishing a trust relationship between the client OIDC consumer and a 3rd party service the client OIDC consumer wishes to establish an identity through the OIDC producer to that 3rd party service.

Party A is an end-user, the JWT consumer Party B is backend service that relies on an identity of party A verified by party C Party C is a 3rd party identity provider, the JWT producer

When you are Party B you don't get to see the secret Party A has that lets them read encrypted data Party C sends unless you act on behalf of Party A and effectively eaves drop on them to capture their response to Party C's challenges. This challenge-response mechanism is Authorisation, it's how trust is established for OIDC and the JWT produced by Party C represents this. Cutting out the party A and misusing OIDC for a 2 party relationship is becoming more common, and it destroys the security characteristics of what OAuth, OIDC, and JWT were meant to provide making this type of 2 party system untrustworthy and may lead to vulnerabilities from the broken implementation.

JWT in microservices

A JWT can also be used in your own microservices architecture simiiar to OIDC where the client makes a request to a server, but the initial server-side process must make calls to other upstream services as the client callers identity, not the identity of the server then a JWT is a good mechanism to carry the client authorisation throughout the microservices stack (and validated by each microservice).

In this scenario you control 2 of the 3 parties, but in all cases each party applies zero-trust and JWT is intended to provide the means to validate a requester's authz during indirect processing of the 3rd party that never directly interacts with the end-user requester.

Derive the meaning behind the question

I am going to make an assumption that you're running services and have controls of only the JWT generator, i.e. a JWT producer, not a JWT consumer. Specifically you would have no control over the JWT client consumers because when a JWT is generated it is designed for purposes where a middle service (your service) facilitates a trust between 3rd party and an upstream (which normally isn't first party but can be).

Therefore you would be generating a JWT for a client to establish trust with an upstream service, and as the JWT issuer you should decide if RSA or ECDSA encryption is needed or if the JWT should simply be a signed proof of established trust or authorisation and not even have any RSA or ECDSA encryption at all.

JWT modes

First need to appreciate that JWT can work in at least 2 modes:

  1. with RSA or ECDSA encryption: ergo the you add additional application specific data to the contents of the JWT payload; this sensitive information would be intended to be read (decipher) by anyone whom controls the private key, but anyone can encrypt (encipher) plain text, typically a 3rd party provider and not the service doing the actual JWT generation because a service generating the JWT needs to validate the authenticity of the issuer (provider) which is obviously not going to work if it claim's "I am authentic, trust me". When you validate the JWT signature for integrity and use encryption, there is also the confidentiality factor needed, which i'll explain further below to ultimately answer the question.

  2. without encryption: the claims in the JWT are not sensitive and you are not adding sensitive application data. This is when JWT using only HMAC is utilised. I.e. with HMAC there must be an out-of-band (rather pre-shared) secret that both sides store. Using the pre-shared secret both side are able to reproduce the same HMAC to validate the JWT integrity.

If you have no sensitive application data sent in the JWT, you are not requiring encryption, you only have a typical scenario where there is some user specific secret needed not specific to JWT, and not encryption. This is a basic application secret problem and what has been explained so far is all that you need to know.

Assure confidentiality

If you have sensitive application data and the JWT implementation is fit for purpose, you must have assurance in your implementation so that only the intended recipients can read the clear text or the use of RSA or ECDSA encryption is meaningless and a wasted effort. To have this assurance you must have the intended recipient (the readers of the content) generate the secret (private key) and NEVER share it, period. The client instead shares the public key with the JWT generator service so it may encipher contents for the recipient in an assured way that only the recipient may decipher back into plain text.

JWT is a claim of Authorisation, not actual Authz

One common misunderstanding of JWT, perpetuated from JWT's influence from OIDC, that the JWT can prove authentication, but it does not at all. It doesn't help that OIDC docs state it is because OIDC was built on OAuth2.0 to provide both Authn and Authz:

Based on the OAuth 2.0 protocol OAuth 2.0 also means having one protocol for authentication and authorisation (obtaining access tokens).

But OAuth 2.0 themselves make it very clear OAuth 2.0 is not an authentication protocol

So when you use JWT, it represents a claim of authorisation only and assumes authentication occurred - i.e. assumes you did your own authentication before.

A JWT by default is neither authentication or authorisation until you verify the JWT claim attributes, i.e. the JWT claims it is authorisation and once you verify the claim attributes it can be trusted as proof of authorisation - but never replaces authentication.

Further assistance

There's quite a lot to learn in the above answer, I encourage you to research more about JWT, ECDSA, RSA, 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.

3
  • What a beautiful answer. So many topics summarized on point! I'd like to highlight the fact that while JWT is common in an authentication flow that requires a third party, it's also commonly used on the application server itself, without an identity provider. I guess, what @user6227254 is most concerned about is key management and techniques that you (must) implement early on in case of a leak that aids in recovery.
    – Advena
    Apr 2 at 9:48
  • @Advena instead of commenting on an anwer from 2021, which is on a question form 2016. maybe ask it as a separate question yourself? irt would get much more views that way.
    – LvB
    Aug 14 at 10:53

You must log in to answer this question.

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