As I know, the token is signed using secret, but if I paste it in jwt.io, I can't modify the Payload because I don't have the secret, but I can see the payload, with the user ID.
I propose encrypt the token (maybe only the payload) with Laravel encrypter before send to the user, and decrypt it in the server where checking it.
To make it without breaking changes, I propose add an option in the config file that encrypts the token when we receive it from attempt, login or similar methods.
| Q | A
| ----------------- | ---
| Bug? | no
| New Feature? | no
| Framework | Laravel
| Framework version | 5.5
| Package version | 2.0.0-rc.2
| PHP version | 7.2
This is crazy. I had no idea JWTs were not encrypted until finding out today by accident. I thought JWT_SECRET was for encrypting the claims!
I was including really sensitive data in the payload -.-
definitely +1 for this ticket!
@amcsi JWT_SECRET is used to sing the token, that means, anything can falsify the token without the secret, but is only signed, not encrypted.
If you're always just encrypting/decrypting and someone gets a hold of your encrypted id, how is that any different than having your raw user_id? An attacker could just send a request to the server with your encrypted id. Your server is responsible for handling authorization. Your application should never authorize a request based on the presented user_id.
Also, if someone has your JWT don't you think they're just going to authenticate with the server using the entire JWT and impersonate you?
Make sure you are storing your JWT in a secure place, such as an encrypted cookie that can only be used in the scope of https://yourwebsite.com/
Also, I'm a little confused about how you can falsify a token without the signing secret? The header and payload of a JWT are concatenated and then signed using a key that the user does not have.
If you present a modified token, you must also regenerate the signature for the server to accept the JWT as a valid token. Otherwise, it will know you modified it.
Please research more about message authentication codes, it will help you better understand how the server is validating that the key was generated by the origin and not modified or generated by another machine. Read more about message authentication codes
@ColinLaws I myself am not saying it can be falsified. I'm just saying that it was problematic that it's not encrypted, because I was including custom _sensitive_ secret data in the JWT claims with the wrong assumption that the data is encrypted and that only the server would be able to read it.
@amcsi I understand, I wasn't under the assumption you thought you could falsify it. It was @montyclt that claims he can falsify it without the secret.
And no, your payload is not encrypted. The JWT is encoded, not encrypted. It uses base64 encoding. You should never include sensitive info inside of the JWT. If you need information about the user, then get the user_id from the token on the server and then query the user for the information you need. If your Javascript client can read a token, it is open to the world (essentially, if your token was compromised). So your token should never include something like, say, a social security number, credit card, etc. Only the claims and an identifier for the user.
@montyclt I think I understand what you were saying now. It's just a language barrier. You are saying that if you don't use a signing secret, then you can falsify it because it isn't signed. That is true. But my point is, don't put sensitive data in a JWT.
@ColinLaws
I think we misunderstood.
I'm signing my tokens and I know no one can falsify without token secret, because he doesn't knows the secret.
I simply emphasized the tokens aren't encrypted and I propose encrypt it.
I know this is old, but this shows a fundamental misunderstanding of JWTs.
If you need to you _could_ encrypt before creating the custom claims, but really @ColinLaws is right, just don't put sensitive info into your jwt. If you have sensitive info then use your jwt to authorize the retrieval of that info in your app.
Except when it's storing your user's key to his encrypted cryptocurrency private key that we don't want to store for security purposes.
But I get it; it's our responsibility to do the encryption.
@amcsi You should not be storing sensitive information in your JWT. It should only describe who the JWT claims to be. If you need to transport sensitive data, use the JWT as a form of authentication to access the information from a protected back-end.
@ColinLaws How should I be storing e.g. credit card information in a secure way then? I don't want to store it in the DB in plaintext, nor do I want the decryption key to be in my DB if I do encrypt the credit card numbers. Thus I want the client to keep sending me the credit card decryption key (encrypted of course) so I wouldn't need to store it.
Sensitive information should be stored encrypted in the database. You wouldn't store the encryption key in the database you're storing the encrypted data in (I hope it's obvious why, that's like putting locks on your doors and keeping the key next to your door).
Another problem is that if you're decrypting data on the front end. If someone stole encrypted data from your front end, wouldn't they just take the encryption key as well?
Storing sensitive data in your browser is risky, and you should make every effort to persist sensitive information to an encrypted data store that is guarded by strong authentication/authorization systems.
Please research security more in depth. You are putting users at serious risk by the methods you are describing. I suggest closing this thread, as the OP is not clear on the properly implementing JWTs.
god damn @amcsi I hope I don't end up using your cryptocurrency software. Have you even read the specification behind JWT and what the point is before blindly assuming what it does? Most JWT implementations will not use encryption for anything besides signature verification. You should know this because cryptocurrency works the same way, transaction information is not encrypted, not even on private chains like Monero. It's merely signed to ensure the contents have been chosen by the trusted authority and not someone else.
You can not reliably store anything on the client side anyways, the contents of your JWT claims are still stored in the database, the only difference is you're transmitting it at every login request (and at EVERY request from the client to the server) with no reason. Finally, whether JWT payload is encrypted or not doesn't matter because HTTPS should not even be a question with this and then the whole contents are encrypted. If the network or the receiving client is compromised then you have bigger problems than someone reading the contents of the payload.
I haven't actually read JWT's specification, indeed. I can only be disappointed at the JWT specification now I suppose, because I feel like there's little performance penalty for using symmetrical encryption, and the spec could have taken the signature bit a step further and demanded symmetric encryption too.
I know that transaction information is just signed, but this is a different situation, because we need to be able to make new transactions, and for that we need the private key, which we need to protect as much as possible.
You do have a point in the last paragraph, but still it's best to be more cautious in case there's some malware that would send back all localStorage data about a user. I believe it's even common for desktop cryptocurrency software to even obfuscate private keys in memory for security reasons (as a more extreme example).
Anyway, I rest my case :P
This is what everyone is trying to say:
You are using JWT wrong.
For example, imagine you want to send someone an item in the mail. You wouldn't mail someone an item in a plastic grocery bag, would you? That's analogous to what we're saying. You are using JWTs incorrectly.
If you are working for somebody, I would let them know to have someone change your code immediately before you're liable for leaking credit card numbers or crypto currency tokens.
If this is a personal project, I would shut down your service and fix it before letting anyone continue to use it.
If you haven't read the specification, go read it, or at least read some material on what JWTs are used for.
@aron9forever Made my point again, if someone has your JWT, they have access to your account. You have way bigger problems if an attacker is able to retrieve information from your client or information that was transmitted over the wire.
If you are working for somebody, I would let them know to have someone change your code immediately before you're liable for leaking credit card numbers or crypto currency tokens.
The whole thing I'm doing is precisely to not leak anything. Storing the private keys encrypted on the server, while only allowing having access to the decryption keys by the user sending them each time with the JWT request. I don't see a better secure way of doing this; I hope you're not suggesting I keep the decryption keys on the server.
Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.