sk8terboi87  ツ
sk8terboi87 ツ

Reputation: 3457

Is it safe to store sensitive data in JWT Payload?

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,

  1. Is JWT only for verifying the signature with server when sending data?
  2. Is insecure to keep sensitive data in Payload?
  3. If insecure, any way to secure the Payload?

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

Answers (3)

Spomky-Labs
Spomky-Labs

Reputation: 16775

  1. Is JWT only for verifying the signature with server when sending data?

No, there is not only signed JWT (JWS - RFC 7515), but also encrypted JWT (JWE - RFC 7516).

  1. Is insecure to keep sensitive data in Payload?

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

daviomey
daviomey

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

Vahid Najafi
Vahid Najafi

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

Related Questions