Why I Switched from JWT to Sanctum
JWT is an amazing authentication system. I came across it when I started working on designing APIs, and with a very good library like laravel-jwt, you do not have to bother about the nitty-gritty of how it works. Just plug it in and everything seems to work. In fact, for some time, I did not really understand why it works; all I knew was that once a token is generated, it can always be used to authenticate a user. laravel-jwt already provides a middleware that handles this out of the box, so that is yet another thing not to worry about. You can safely get away with not knowing anything about JWT.
Why JWT?
JWT is not the only means of authenticating APIs; there are several options for developers. I fell in love with JWT because it prevents having to make an additional trip to the database to authenticate users. JWT tokens are not stored anywhere on the server, as the token itself already contains all the information you need to always authenticate a user when it is passed. All you need to do is decode the JWT token and extract the required information. An example could be adding the user ID to the payload and then using it to authenticate users subsequently. This way, you completely avoid a trip to the database while still maintaining the security that comes with JWT.
I also loved the fact that the tokens are not stored in the database or anywhere at all.
Why the Switch?
While working on a project for which I had used JWT for its authentication, there was a need to ensure that a user can only log in to a single device at any point in time. For example, if a user logs in on mobile, the user should be automatically logged out of any other device having an active session. This was a security concern that needed to be fixed.
Upon implementing this feature, there was no way I could think of to implement this using JWT since new tokens would be generated for each device that the user uses to sign in to the app. Of course, this can be solved by keeping a record of the token and the corresponding owner in persistent storage (database, cache, files) and using this to track which token to revoke upon subsequent use. However, this already defeats the purpose of JWT and we are completely out of the JWT paradigm.
The beauty of JWT is that there is no need for persistent storage; hence, upon introducing storage, it might be a sign that it is not a good fit for the system. Laravel Sanctum is an authentication library managed by the core Laravel team to handle token-based authentication and has a cookie-based authentication for single-page applications built with Laravel.
At the core, it generates a token upon a user's attempt to sign in. This token is stored in the database along with the owner's information. Every sign-in attempt creates a new token, and since the tokens are stored in the database, existing tokens can be deleted when new ones are created. This immediately ensures that all existing sessions are invalidated since the tokens used for those sessions would no longer be valid.
Tokens can also be assigned names, so I was able to associate each token with the device name, allowing users to revoke tokens for specific devices while allowing others to remain. The benefits this comes with go way beyond the comparative advantage of JWT for the project I was working on, and I eventually made it a default authentication preference when building applications.
However, I still find JWT useful in some other cases, such as authentication between machines in a microservice system where sophisticated authentication requirements are not required.