3 comments

[ 0.19 ms ] story [ 16.5 ms ] thread
Wow, I found this to be a naive view of JWT usage. I'm not advocating it's usage for every circumstance, and, the author does add the disclaimer that he knows little about it, but I feel the author misses a number of basic concepts of JWT's. Here are some observations:

1. you are able to decode the headers and payload of the token regardless of what algorithm was used. This is because both are base64 values of the content they represent. The purpose of the JWT is to securely identify a user in a stateless environment. The token's use is therefore to pass basic user information (as well as token information for purposes of identifying how to decrypt the token, it's validity time, etc) along, while identifying the user at the same time. The former requires that data be easily readable, hence the base64 hashing of that content. The latter part is achieved by using an algorithm that generates the signature of the token using the first 2 parts and by providing a secret key. If the data in the token is modified in any way, the signature won't match. Hence the validation of the token fails.

2. You should never be including any sensitive data in the payload of the token. Such as password hashes. The example given in the post is akin to a developer storing a users sensitive details in a cookie. You could probably get away with "higher sensitivity" data stored in cookies in certain cases, but overall it's just wrong and as a developer one should know better.

3. Persistence of tokens is typically an issue admittedly. How I've typically countered such things is using shorter token lifespans, as well as such things as the inclusion of a "session" key on my users table. This doesn't prevent a db lookup, but the value of which can also be saved to a redis instance for example. The value of this field remains mostly static and can initially be the same across all users for example, and the value of which is included in the token payload itself. For example, all users can have the same value of 1 (very simple case, but bear with me). Now, if you need to invalidate a user session for some reason, or log them out of all their devices, or some similar action, simply change the value of this field. Your token validation would need to include a check against this value as well which makes this not very different to session storage (or rather a user cache) , but it's not a worse performance than server session storage and because the value remains mostly the same, is actually easier to implement in my opinion.

4. A single key used to sign all user tokens is generally a bad idea to begin with regardless... but that's like not salting passwords or taking any proper measures when securing users. The case mentioned in the post could be likened to someone accidently typing out an admin password for a web login in a public forum... in which case, shit happens. Sure, in such case it's easy to update the password without affecting user logins, but to be fair, the use of insecure methods for security in general rarely if ever leads to secure implementations. Can't expect a sturdy wall if you don't plaster the bricks together. So related to my point 3 above, use of the user's password hash, for example, or some other, non public, identifier in addition to the signing key helps tons. Or use an RSA implementation signing algorithm. If however, you want HMAC, or such, your performance using a user cache is not unlike server side session storage, and is easier to implement and maintain. All the while keeping the benefits of JWT.

Again, not for every use case, but it's not as broken or insecure as the post makes it out to be.

Hey Wetwiper, i like your Nickname :) thanks for the review :-) 1. Yeah, I do understand the working of JWT and Signatures, it was made in a simpler format for naive first time users. There is no security flaw in that 2. Yeah, you are right in a way, but I have seen people do it in case of JWT, as they store the User-id there as well 3. Hahaha.. that's a DB lookup, you loose ;-) 4. I don't understand how multiple would work. Well, as for your "insecure methods" comment, I have a classic example of employees leaving the Tech team. And as for Signing algorithm you can never say anything. A few years back MD5 was considered most secure and could not be broken and used in every Digital Signature. Now there are websites that generate the text based on the HASH value.. that is not using Rainbow tables. So, even salts in this case wont work :-|

I agree, that my review was biased (isn't everyone? :-o )

Hehe... nick chosen for a variety of reasons :) I'm going to point out that storing user IDs and such in the payload is perfectly acceptable, and one possible means of transporting a user id around rather than as part of a url path, query string, etc. Because the payload is typically meant to be readable, there should never be any sensitive data like password info added to it. Note that while JWTs are used for authentication typically, thru are also used as a means of secure message passing. Anyway, proper use of a technology comes down to developer awareness, but I would hope that the developer implementing any means of security would do some research into doing it properly. We can't blame the tool for being used incorrectly :) Perhaps the problem in this case is a lack of sufficient proper documentation? Can't say I've found lack of docs to be a problem, but I guess people's mileage differs.

As for my points 3 and 4, I did mention that they included a DB lookup. I don't believe I've ever read anything that claims that it prevents a DB hit. In fact, this[1] page states that they help to prevent more than 1 DB hit for user info. However, what I was trying to allude to in my previous comment was that you can store the bare minimum info of your users in a cache. This cache can be used during the validation of the token (and even with token generation) , which prevents a db lookup. Since the data in the cache should contain data that rarely changes (should only typically be updated on password change, or when any of the details used in the payload of the token changes) , management and maintenance of your user cache is simpler. Specifically on point 4, what I was suggesting is that if you are planning on using something like HMAC as the algorithm for signing, then the signing and validation steps of the token can include the password hash or similar unique value for the user in addition to whatever key is provided. In addition, if your tech team has access to your production DB, you have a concern when anyone leaves anyway, regardless of what authentication method you are using. So not really something specific to JWT. In the case of JWT and using HMAC for example, I would have my production key stored in the prod environment only.

I will say that changing a key is a real concern, if your key does become compromised... but it is possible with a bit of thinking upfront about it. I've successfully implemented something like this previously.

Again, it's not the right tool for every circumstance, but when used in the right circumstance and in the correct way, I don't find most of your post to be relevant (meant with good intentions and I'm not trying to be provocative).

Perhaps a quick read through the Wikipedia page [0] on the topic, but more importantly, the JWT IO page [1] on the matter provides usage and implementation guidelines, as well as confirms some of what I've mentioned previously.

[0]: https://en.m.wikipedia.org/wiki/JSON_Web_Token [1]: https://jwt.io/introduction/