Reputation: 3457
I'm currently learning JWT implementation with PHP and want to use JWT tokens instead of sessions for my RESTful application.
During signature creation, I'm doing something like this
token = base64Header + '.' + base64Payload + '.' + signature
Here we are just using base64 the Payload. If I paste in sites like https://jwt.io/#debugger, the Payload gets decrypted (even if the signature is wrong).
My questions,
Below is the sample code I wrote
<?php
$headers = base64_encode(json_encode([
"typ" => "JWT",
"alg" => "HS256"
]));
$claims = base64_encode(json_encode([
"sub" => "1234567890",
"name" => "John Doe",
"admin" => true,
"jti" => "870a3de5-ea7b-4062-abef-11180e530f5a",
"iat" => 1492603378,
"exp" => 1492606978
]));
$payload = $headers.".".$claims;
$signature = base64_encode(hash_hmac("sha256", $payload, 'secret', true));
$encodedJWT = $payload.".".$signature;
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6Ijg3MGEzZGU1LWVhN2ItNDA2Mi1hYmVmLTExMTgwZTUzMGY1YSIsImlhdCI6MTQ5MjYwMzM3OCwiZXhwIjoxNDkyNjA2OTc4fQ.nvw-bAUgr7H_xr3q8_Yz8rCNtMohtn2YlCmcLoLBWlc
Upvotes: 19
Views: 15585
Reputation: 16775
No, there is not only signed JWT (JWS - RFC 7515), but also encrypted JWT (JWE - RFC 7516).
When a JWT is encrypted, you can share sensitive data securely (unless the algorithm or the key are compromised).
But in your example I see no sensitive data, thus I am wondering if it is really important to use JWE in your case. I highly recommend you to read this blog post about JWT and sessions and why you should not use them for that purpose (also take a look at that part 2).
If you really want to use JWE, then I wrote a PHP library that is already able to load and create any kind of Jose (JWS/JWE) and that supports almost all algorithms from the RFC 7518 out of the box. Other libraries may exist, but there is no references list (https://jwt.io/ lists only JWS implementations).
Upvotes: 6
Reputation: 394
If I paste in sites like https://jwt.io/#debugger, the Payload gets decrypted (even if the signature is wrong).
Third parties cannot verify the signature because they don't have the secret key. The payload doesn't get decrypted - it gets decoded.
Ideally you should not store sensitive data in the payload since the payload is only base64 encoded and not encrypted. This means anyone who gets a hold of the token can view the contents of the payload by simply base64 decoding it.
If you have a token in local storage of a web browser and your site has an XSS vulnerability it makes it trivial to steal the token. It's bad enough that the attacker has a valid JWT (which will hopefully expire soon anyway) but if it contains sensitive data then you're in real trouble. Imagine having to notify all users on your site that they must now change various bits of sensitive data about themselves because of a potential mass compromise.
Keep the JWT lightweight. Store the users ID, their roles/grants withing the system. If you feel like you have to add sensitive data to the payload try and rethink your solution.
Upvotes: 27
Reputation: 5263
As I understood, you're trying to have a complete stateless
server, so you want to store even sensitive data within the token.
But your server cannot be completely stateless. Because for logout functionality, you must have either a black list or white list in order to invalidate the token. So in each request you must touch the database. If you don't have black list or white list, the tokens are still valid even when user logs out.
So, it's better to get the sensitive data from database, as you should touch your db per every request.
Upvotes: 7