0

Trying to get my head around not using traditional $_SESSIONS to keep user logged-in across pages. Are there security issues with storing JWT in cookies to authenticate a user session?

Here's a bare example of what I'm trying to do:

config.php

$key = "secret123";

login.php

use Firebase\JWT\JWT; // A simple library to encode/decode JWT

require 'config.php';

// ... assumed valid user/pass, set cookie session

$token = ['uid' => 123];    
$jwt = JWT::encode($token, $key);    
setcookie('jwt', $jwt);

// redirect to private page

private_page.php

require 'config.php';

if (isset($_COOKIE['jwt'])) {

    // check if JWT is tampered
    try {
        $decoded = JWT::decode($_COOKIE['jwt'], $key, ['HS256']);
    } catch (Exception $ex) {
        echo 'Invalid authentication';
    }

    echo 'You are logged in as uid '.$decoded['uid'];
}
else {
    echo 'You are NOT logged in';
}

Is this implementation secure enough, what other things should I consider?

IMB
  • 2,888
  • 6
  • 28
  • 42
  • Is there a particular reason you want to use JWT? What part of traditional sessions doesn't work for you? – Sjoerd Apr 22 '19 at 19:35
  • @Sjoerd for leaning purposes and don't want to deal with scaling issues (which is not really a big deal but it's one task less nonetheless). – IMB Apr 23 '19 at 05:32

1 Answers1

1

There are several issues when using JWT instead of session cookies:

  • The client can view the data stored in the JWT token. With sessions, this data remains on the server.
  • Logging out is complicated. When the user logs out of the application it is hard to stop the JWT token from being valid.
  • The data in the JWT can be out of date. If a user changes his username, he still has a valid JWT token containing his previous username, while that doesn't exist in the database anymore.
  • There have been some bugs in JWT libraries (and maybe even the specification?) that have reduced trust in the JWT system. Particularly the decision to let the client provide the JWT type (HS256 or RS256) is considered risky.
  • It relies on a key you need to keep secure. If someone compromises your key they can forge valid tokens.

Valid uses of JWT tokens involve single-sign on implementations, especially OpenID connect, where multiple systems are involved. They are not a good alternative for traditional sessions.

Some links:

Sjoerd
  • 28,707
  • 12
  • 74
  • 102
  • Thanks for the reply. It seems there are workarounds with the issues you pointed though. E.g., `1.` In my e.g., the client don't know the encryption key right? And even if they decrypt it i'm ok with it since it's just a user id, no harm done. `2.` I'm storing the JWT inside a cookie so I can invalidate the cookie instead. `3.` Same as #2. `4.` looks fixed now. `5.` I think it's it's an acceptable risk that is always present in webapps e.g., same issue as DB credentials / API key storage, hard to completely secure. – IMB Apr 23 '19 at 05:38
  • Again thanks for the input. I'm not looking to discredit traditional sessions at all just want to have someone take a look at my implementation. Seems "stateless sessions" is still a viable alternative as long you're aware of the issues involve. – IMB Apr 23 '19 at 05:48
  • Actually, my bad in `#1`, client can indeed still see the data but still ok since it's just uid. – IMB Apr 23 '19 at 08:21
  • Thinking about my example, I am simply using JWT as an encryption mechanism and cookies as storage. Meaning I could actually ditch JWT altogether and use a better encryption library instead. What you think? – IMB Apr 23 '19 at 08:46