Sessions vs. Token based authentication

31,397

The question on Information Security linked in the comment above has a lot of relevant information. That being said, a few additional concerns raised in this question should be addressed:

Safety

Knowing nothing about the server implementation, both methods can be as secure. Session-based authentication mostly relies on the guessability of the session identifier (which, as described in the Information Security answer, it in itself a very simple token). If the session identifier is a monotonously incrementing numeric id, then it is not very secure, OTOH it could be an opaque cryptographically strong unique ID with a huge keyspace, making it very safe. You are probably going to use the session implementation offered by your server framework of choice, so you need to check that. After that, using session authentication, your server implementation needs to verify that the server stored session contains the relevant authorization (i.e. user account data, role, etc) - as a lot of server session frameworks will be default auto-generate empty sessions as needed, the fact that a session exists must not be relied upon as proof enough for a valid authentication and authorization.

For example, PHP's internal session ID generation uses a completely random 288 bits number (default setting) so it is considered safe, OTOH - by default it generates sessions automatically so the previous comment must be adhered to (or to disable automatic session creation and make sure the server only creates session as needed).

Also, if the session ID is passed using an HTTP URL query string, as was the default in days of old, then the session can be stolen quite easily and that makes the whole process insecure.

Token safety is mostly based around secure token generation: if the server generates tokens in a secure manner - i.e. non-guessable and verifiable - as demonstrated in the Information Security answer. A naive implementation (that I saw one time) might be to MD5 hash a known token, such as a user name, and that makes it very unsafe, even when salted. When using cryptographic tokens, safety is closely related to the strength of encryption which is determined by the algorithm used, length of the key, and - most importantly - how well the server key is secured: if the server key is hard-coded into the server implementation and that code is then open-sourced...

Storage

Whether the server needs to store anything generally depends on the implementation of the tokens.

A lot of implementations use the concept of an "API key" as "token authentication" and so often tokens are just some cryptographically secure ID to a database that records which "API keys" have been generated. This requires storage but has the advantage of a simpler implementation and - more importantly - the ability to revoke tokens.

The other approach is to have the token carry its own authenticity - this allows the server to essentially offload the storage of tokens to the client and use the client as the database - very much like how HTTP Cookies allow servers to offload some storage requirements to the client (often used for client's specific settings, like whether the user wants a light interface or a dark interface).

The two patterns used for this are demonstrated well in the Information Security answer: signing and encrypting.

  • Signing: The token is some simple encoding (like JSON or CSV) of the authenticator credentials (such as the username) and possibly the token's expiry time (if you want to have tokens expire - generally a good idea, if you can't revoke tokens), and then the server signs the generated text using a server secret and adds that to the token. When the client submits the token, the server can extract the clear text from the token, re-sign it and compare the new signature to the signature part in the submitted token - if they are identical, then the token is valid. After validation, you probably want to check the validated expiry date against the current time. The main disadvantage here is that care should be taken that the clear-text authentication details are strongly insufficient for an attacker to re-authenticate - otherwise, it harms the safety requirement. i.e. don't send the password as part of the token, or any other internal detail.

  • Encrypting: the token is generated by again encoding all the relevant authentication details and then encrypting the clear-text with a server secret and only submitting the encrypted result. If the encryption scheme can be trusted, the authentication details can include internal data - but care should be taken as having a large crypt-text available offline to an attacker is a larger attack surface than a small signature and weak encryption algorithms will be less resilient in this usage than in just signing.

In both methods, safety is closely related to the strength of the encryption/signing algorithm - a weak algorithm will allow an attacker to reverse engineer the server secret and generate new valid tokens without authentication.

A personal note

In my opinion, cryptographic token-based authentication tends to be less safe than session-based, as it relies on the (often single) developer doing everything right from design to implementation to deployment, while session-based authentication can leverage existing implementations to do most of the heavy lifting, where it is very easy to find high-quality, secure and massively used and tested session storage implementations. I would need a very compelling reason as to why session storage is unwanted before recommending using cryptographic tokens.

Always remember the no.1 rule of cryptographic security: never design your own single-use cryptographic measures.

Share:
31,397

Related videos on Youtube

which_part
Author by

which_part

Updated on July 09, 2022

Comments

  • which_part
    which_part almost 2 years

    I want to know which is more safe to implement for authentication and why? Session based authentication OR Token based authentication?

    I know sessions can be used for other things as well, but right now I am only interested about authentication.

    Is it true that nothing is stored on server side if using tokens (not even in memory)? If yes, then how it identifies against expired tokens as that had also been signed using the same secret?

  • Arpit Anand
    Arpit Anand almost 3 years
    I am sorry for necroposting, but isn't session-based authentication heavy on the database transactions, and hence costing more money??
  • Guss
    Guss almost 3 years
    @ArpitAnand usually your application will already need to use server storage for something so the cost of storing the auth data will be negligible. Otherwise, if you are looking to postpone investing in storage, strong self-attesting cryptographic tokens may be a good choice - but please note that these require a lot more thought and practice to get right - and these do not come cheap either.
  • Arpit Anand
    Arpit Anand almost 3 years
    Okay, but what if we choose to use a library like jsonwebtoken? They provide a pretty neat abstraction of the node crypto library - less code so lesser chances of error!
  • Guss
    Guss almost 3 years
    @ArpitAnand JWT is a big standard with a lot of options and you should have a clear understanding of its purpose, use, and mechanics before employing a library that implements it. For example here's one way that using JWT for authorization will fail you - jsonwebtoken only supports signing and not encryption, so anyone who gets your token can understand your token internal structure and gain a better understanding of how to attack you (or you just might leak internal data that the user shouldn't have).
  • Arpit Anand
    Arpit Anand almost 3 years
    Of course, if the data is sensitive, then the JWT can be encrypted before sending it out to the users. And regarding the data leakage, it is mostly up to how well the developer has concentrated upon not allowing the JWT to contain any unnecessary data regarding the user. Isn't it?
  • Guss
    Guss almost 3 years
    @ArpitAnand from my reading of the npm library jsonwebtoken's documentation - it does not support encryption. Being minimal in what you output is always a good idea, but the minimal required details might include things you wouldn't want the user to know, such as their secret key. In summary - token based authorization requires the developer to be extra diligent, and there is no way to work around that basic requirement.
  • Arpit Anand
    Arpit Anand almost 3 years
    Okay, but isn't this a way how encryption is done using jsonwebtoken? jwt.sign(payloadObj, PRIV_KEY, { algorithm: 'RS256'}); and to verify: jwt.verify(signedJWT, PUB_KEY, { algorithms: ['RS256'] }, (err, payload) );
  • Guss
    Guss almost 3 years
    Nope, that is signing - which means the receiver sees the cleartext and can verify that you created it. Sightly related (just saw it now): mobile.twitter.com/FiloSottile/status/1399700873798893571/ph‌​oto/…
  • Arpit Anand
    Arpit Anand almost 3 years
    Actually, the encryption I was referring to was the asymmetric encryption done by RSA algo by using public and private keys after hashing the payload data created using the SHA256 hashing algo. But you are right, in order to protect the payload itself another layer of encryption should be performed on the finally created JWT so that the payload data is not visible to anyone.
  • Guss
    Guss almost 3 years
    If you are using JWT for the encryption but then need to encrypt the resulting text token yourself, then you are missing the point. Unless you have a strict requirement for JWT, maybe it is better to not add another huge protocol implemented incompletely.