Authentication — Traditional vs JWTs

HTTP is a stateless protocol and is used to transmit data. It enables the communication between the client side and the server side. It was originally established to build a connection between web browsers and web servers.

Let’s understand this with the help of an example: Suppose we are shopping online (or generally e-commerce sites follow this approach), we add some items eg. headphone to our cart. Then we proceed to look for other items, during this time, we want the state of the cart items to be stored and not lost while performing any further tasks. This means that we want our states to be remembered during the entire shopping operation.

Since HTTP is a stateless protocol, to overcome this, we can use either session or tokens.

Server Based Authentication (The Traditional Method)

Before the emergence of JSON Web Tokens, we predominantly used this type of authentication. In this type of authentication method, the server is responsible for the authentication and the client does not know what happens at the server side after sending a request.

Since the HTTP protocol is stateless, this means that if we authenticate a user with a username and password, then on the next request, our application won’t know who we are. We would have to authenticate again.

Let’s understand what happens typically when a user logs into any website on the web browser. For instance, the user logs in, the server will create a session for the user and store the session data in the server memory. There is a session ID created which is stored in a cookie in the client’s browser while the user performs certain activity on the website. On every request that the user makes, a cookie is sent along with it.The server can then verify the session data on the cookie with the session data stored in the server memory when the user logged in initially. When the user logs out from the website, that session data is deleted from the database and the server memory.

So, the traditional way of having our applications remember who we are is to store the user logged in information on the server. This can be done in a few different ways on the session, usually in memory or stored on the disk.

As the web, applications, and the rise of the mobile application have come about, this method of authentication has shown problems, especially in scalability.

The Problems with Server Based Authentication

A few major problems arose with this method of authentication.

Sessions: Every time a user is authenticated, the server will need to create a record somewhere on our server. This is usually done in memory and when there are many users authenticating, the overhead on your server increases.

Scalability: Since sessions are stored in memory, this provides problems with scalability. As our cloud providers start replicating servers to handle application load, having vital information in session memory will limit our ability to scale.

CORS: As we want to expand our application to let our data be used across multiple mobile devices, we have to worry about cross-origin resource sharing (CORS). When using AJAX calls to grab resources from another domain (mobile to our API server), we could run into problems with forbidden requests.

CSRF: We will also have protection against cross-site request forgery (CSRF). Users are susceptible to CSRF attacks since they can already be authenticated with say a banking site and this could be taken advantage of when visiting other sites.

With these problems, scalability being the main one, it made sense to try a different approach.

How Token Based Works

Token-Based Authentication: In token-based authentication, we use JWTs (JSON Web Tokens) for authentication. This is the widely used method for RESTful APIs.

Here, when the user sends a request for user authentication with the login details, the server creates an encrypted token in the form of JSON Web Token (JWT) and sends it back to the client. When the client receives a token, it means that the user is authenticated to perform any activity using the client.

The JWT is stored on the client side usually in localStorage and it is sent as an unique key of that user when the user requests any data from the server or is performing any activity for that website. So, when the request is received by the server, it validates the JWT for every request that it is that particular user only and then sends the required response back to the client.

This is how the header is sent along with every request to the server :

headers: {
"Authorization": "Bearer ${JWT_TOKEN}"
}

The user’s state is stored in the JWT on the client side. When the user logs out, the token is deleted from the Client side(localStorage). Thus, most of the data is stored in the client side and accessed directly instead of sending requests to the server.

JSON Web Tokens consists of three parts concatenated by dots (.):

  1. Header
  2. Payload
  3. Signature

JWT structure:xxxxx.yyyyy.zzzzz

The output contains three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments, while being more compact when compared to XML-based standards such as SAML.

JWT that has the previous header and payload encoded, and it is signed with a secret as shown in the following image.

Structure of a JWT :

Token based authentication is stateless. We are not storing any information about our user on the server or in a session.

This concept alone takes care of many of the problems with having to store information on the server.

No session information means your application can scale and add more machines as necessary without worrying about where a user is logged in.

HTTP is stateless. All the requests are stateless. However, there are situations where we would like our states to be remembered. For example, in a on-line shop, after we put bananas in a shopping cart, we don’t want our bananas to disappear when we go to another page to buy apples. ie. we want our purchase state to be remembered while we navigate through the on-line shop!

To overcome the stateless nature of HTTP requests, we could use either a session or a token.

Read here @ https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci for more.

Who Uses Token Based Authentication?

Any major API or web application that you’ve come across has most likely used tokens. Applications like Facebook, Twitter, Google+, GitHub, and so many more use tokens.

Although this implementation can vary, the gist of it is as follows:

  1. User Requests Access with Username / Password
  2. Application validates credentials
  3. Application provides a signed token to the client
  4. Client stores that token and sends it along with every request
  5. Server verifies token and responds with data

Every single request will require the token. This token should be sent in the HTTP header so that we keep with the idea of stateless HTTP requests. We will also need to set our server to accept requests from all domains using

Access-Control-Allow-Origin: *.

What's interesting about designating * in the ACAO header is that it does not allow requests to supply credentials like HTTP authentication, client-side SSL certificates, or cookies.

Once we have authenticated with our information and we have our token, we are able to do many things with this token.

We could even create a permission based token and pass this along to a third-party application (say a new mobile app we want to use), and they will be able to have access to our data — but only the information that we allowed with that specific token.

The Benefits of Tokens

Tokens are stored on client side. Completely stateless, and ready to be scaled.

Our load balancers are able to pass a user along to any of our servers since there is no state or session information anywhere.

If we were to keep session information on a user that was logged in, this would require us to keep sending that user to the same server that they logged in at (called session affinity).

This brings problems since, some users would be forced to the same server and this could bring about a spot of heavy traffic.

Not to worry though! Those problems are gone with tokens since the token itself holds the data for that user.

The token, not a cookie, is sent on every request and since there is no cookie being sent, this helps to prevent CSRF attacks. Even if your specific implementation stores the token within a cookie on the client side, the cookie is merely a storage mechanism instead of an authentication one. There is no session based information to manipulate since we don’t have a session!

The token also expires after a set amount of time, so a user will be required to login once again. This helps us stay secure. There is also the concept of token revocation that allows us to invalidate a specific token and even a group of tokens based on the same authorization grant.

Extensibility (Friend of A Friend and Permissions)

Tokens will allow us to build applications that share permissions with another. For example, we have linked random social accounts to our major ones like Facebook or Twitter.

When we login to Twitter through a service (let’s say Buffer), we are allowing Buffer to post to our Twitter stream.

By using tokens, this is how we provide selective permissions to third-party applications. We could even build our own API and hand out special permission tokens if our users wanted to give access to their data to another application.

Multiple Platforms and Domains

We talked a bit about CORS earlier. When our application and service expands, we will need to be providing access to all sorts of devices and applications (since our app will most definitely become popular!).

Having our API just serve data, we can also make the design choice to serve assets from a CDN. This eliminates the issues that CORS brings up after we set a quick header configuration for our application.

Access-Control-Allow-Origin: *

Our data and resources are available to requests from any domain now as long as a user has a valid token.

Standards Based

When creating the token, you have a few options. We’ll be diving more into this topic when we secure an API in a follow-up article, but the standard to use would be JSON Web Tokens.

This handy debugger and library chart shows the support for JSON Web Tokens. You can see that it has a great amount of support across a variety of languages. This means you could actually switch out your authentication mechanism if you choose to do so in the future!

Conclusion

This was just a look at the how and why of token based authentication. As is always the case in the world of security, there is much, much, much, much (too many?) more to each topic and it varies per use case. We even dove into some topics on scalability which deserves its own conversation as well.

This was a high level quick overview, so please feel free to point out anything that was missed or any questions you have on the matter.

In our next article, we’ll be looking at the anatomy of JSON Web Tokens. For full code examples on how to authenticate a Node API using JSON Web Tokens, check out our book MEAN Machine

Experience with Front-end Technologies and MERN / MEAN Stack. Working on all Major UI Frameworks like React, Angular.