Search code examples
expressauthenticationjwtcookie-session

Express signed cookie vs JWT as cookie for Authentication


First let me start by saying, this is not a question of client token vs server-side session reference. I understand the differences and I've already decided on a session-less implementation.

I've also decided to use cookies for client-side persitance and transmission rather than localStorage, query param, auth headers, etc.

Ok, with that out of the way, I'm looking at two alternatives to save userID on the client. Both prevent tampering via signing of the data.

Express has a middleware which enables signed cookies, or I could use a JWT which also signs the data (which I would still send via a cookie).

So far, my thinking is to use signed cookies, it's got less processing overhead and does a specific thing and I don't necessarily need my data in nested json format. Also, I'm using it only for authentication of users on my webserver, not for API's or other authorization. I don't need a public/private asymmetric key validation.

JWTs are nice standards, and I will already be using it for OAUTH, but for my site auth, I don't need some of the benefits. For example, I don't need it for transferability. I will not have different sig algorithms or token types.

However I do appreciate that JWT's are a recognized standard and have lots of support/documentation.

Is there something I'm missing on why I should instead choose to use JWT's for website authorization and client identification?

BTW, I have done research on this before posting the question. Here is a very similar one, JWT vs cookies for token-based authentication

However the top voted answer doesn't apply for a few reasons. Chiefly, I've already decided to use cookies for JWT or not. I will be using cookies with options like sameSite to prevent CSRF attacks, along with: expires, secure, httpOnly, and signed (which is particular to express).


Solution

  • So far, my thinking is to use signed cookies, it's got less processing overhead and does a specific thing and I don't necessarily need my data in nested json format. Also, I'm using it only for authentication of users on my webserver, not for API's or other authorization. I don't need a public/private asymmetric key validation.

    By using cookie-parser's signing option your cookie will look something like: user_id=111.base64Signature The main problem here is that your token doesn't have an expire on it, so even if you put an expiration on the cookie, if by some way the cookie was stolen and used, your server will be accepting these requests. The solution is adding a timestamp on the token itself. So now your payload will probably be converted to json and will look something like this:

    {
       userId: 111,
       exp: 1637437857
    }
    

    and the cookie: token='{"userId":111,"exp":1637437857}'.base64Signature. so now if you base64 encode the payload basically the only difference here from a JWT is the header: token=header.payload.signature.

    In regards to performance you will get the same results (if using json format for the payload) since the method to create the hmac is node's crypto.createHmac and is used in both the express middleware and by the common jwt libraries (jsonwebtoken / express-jwt) using symmetric signatures.

    I think if you decide to implement expiration, the JWT formatting will enable you to use different libraries and get free validation checks (which seem to lack in cookie-parser middleware), if you have no need for this then your solution will do the job.