Authentication 101 — Tokens vs. Cookies
The beginners guide to understand token-based and cookie-based authentication.
With the rise of single-page applications and native mobile apps, token-based authentication has grown increasingly popular. But what exactly is token-based authentication, and how does it differ from cookie-based authentication?
To answer those questions, we must understand the difference between stateless and stateful applications.
Stateful versus Stateless
We mainly interact with stateful web-applications. For instance, when a user navigates to Amazon, unauthenticated, they don’t have access to their Amazon account. However, when a user logs into Amazon, they can see their orders and add items to the cart. And if the user adds an item to the cart and navigates to another page, the items in their cart persists.
Stateful applications retain a persistent connection between the client and server. Each request is dependent on the previous request, and if a request is interrupted, the subsequent request can continue where the last request left off because the state of the application is stored somewhere. Stateful applications also need to differentiate between different sessions.
On the other hand, the world wide web is developed on a stateless protocol, HTTP. In every HTTP transaction, the server and client acknowledge each other and then share some information. Once the transaction end, the client and server forget the other exists.
Stateless applications don’t retain any information after a request; every request is a brand new and completely independent.
So if the world wide web is stateless, how do we build stateful applications on top of this system?
The dilemma introduces the traditional cookie-based authentication method. Cookies are small data files that contain information about a particular web session. Cookie authentication is stateful. Information about an authentication session must be maintained on both the client and the server.
When a user logs in using their credentials, the server creates a session, stores it in persistent storage such as a database, and provides the client with a session identifier. The session identifier is then used on every request to verify a session using the session data stored on the server.
There are two types of cookies. Persistent Cookies are stored on a user's hard drive. They allow users to revisit a website already authenticated, even if the user closes the browser or restarts their machine. These types of cookies also have an expiration date that's issued by the webserver.
On the other hand, session cookies are temporarily stored in memory. If the user closes their tab, browser, or restarts their machine, the session is destroyed.
The downside to cookies is they’re difficult to maintain. Cookies are bound to a single domain. This isn’t ideal for single-page applications because SPA can make requests to different types of services. Cookies are also maintained in two places, the client and server. When a user logs out, the session must be destroyed in both places. Furthermore, there’s a bit of overhead to do a lookup on the server on each request to persistent storage.
Token-based authentication solves some of the cons to traditional cookie-based authentication. Token-based authentication is stateless. The server doesn’t need to know about session data. The server only signs and verify tokens to determine if a session is valid.
When a user logs in using their credentials, the server generates an encoded token from the server and returns it to the client. The server doesn’t have any knowledge of the token after that. However, when the server receives a token in a request, it’s able to decode it and verify a session. The token can be stored on the client in a cookie, in which we can make use of the different types of cookies. However, the method of authentication is still token-based.
Since the server doesn’t need to store session information, there’s no need to do a lookup in persistent storage for every request. Therefore, it removes some heavy overhead. Tokens are also not bound by a single domain. An application may have multiple tokens to access different services.
However, there are still some downsides to token-based authentication. Tokens need to be stored somewhere on the client. Each location, such as local storage, cookies, sessional storage, has pros and cons. So, developers should choose wisely.
Tokens are also more susceptible to cross-site scripting (XSS) and cross-site request forgery (CSRF) attacks. XSS attacks are an injection type attack where an intruder injects malicious scripts onto trusted websites. Since tokens are stored on the client, it’s easy for a malicious script to steal tokens. CSRF attacks allow intruders to perform actions in the guise of the victim. Intruders can fulfill HTTP requests to APIs using a user's token. There are preventative measures. However, it’s still a tedious issue to deal with that adds to development time.
JSON Web Tokens
JSON Web Tokens, also known as JWT, is an open standard (RFC 7519) and is a way of transferring data using JSON. There are different types of tokens to utilize, some of which are JWT related and some that are not.
Access Tokens aren’t exclusive to JWT, and they’re used to access APIs. The bearer of an access token is allowed to make requests to an API under some scope. Scope are the types of actions or requests the end-user can make to an API. Access tokens aren’t used for client-side authentication; they primarily protect backend resources.
ID Tokens, on the other hand, are JWT, but they’re meant to be used by the client. These types of tokens provide essential and basic data about the user to the client.
It’s important to note that none of these tokens should contain sensitive user information.
Hopefully, this clarified any uncertainties.
Happy coding! ❤