JWT vs Session Authentication

Authentication

The topic looks obviously obvious and generally speaking standard user doesn’t care much about the details. He wants to register, login, and make sure that his password is safe. The more you read and learn, the more sophisticated requirements you have for protection, state management on the server and client side, the more things are getting complicated.

The problem with authentication is basically about: how does one prove that he is the guy that he’s pretending to be? In the world of web development, the general use cases are:

  • register with a login and password
  • login by providing login, password and validating it is the same as provided during registration
  • after logged in, authorize access to the specific resources during the whole period of website usage, so that one does not need to navigate to the login screen all the time

So when working with websites, you have to clearly separate the client and the server. The client – browser – is handling user input and sending it to the server. Now on the server side, we have to persist the authentication data so that we could verify them afterward, each time user wants to log in.

In order to avoid keeping passwords in plain-text, passwords are very often hashed upon registration, so the server (database, supposedly) only keeps hash. The password itself isn’t really necessary when user will try to log in, the password he will enter is gonna be hashed and only hashes will be compared. This prevents anybody from knowing the passwords only looking at the storage values. Hash functions are meant to be one-way functions (although, nobody can prove such functions do exist), so there is no easy way to recognize password looking only at the hash value.

An additional layer of security comes from SALT usage, which represents some random data that is added to the password before hashing. Adding random content to the passwords is supposed to prevent from attacks based on dictionaries and if used very often in passwords hashing.

In my project, I am using the bcrypt-nodejs library, which allows you to hash passwords easily, handles salt and lets us focus on other things. Simple as that:

var bcrypt = require('bcrypt-nodejs');
//hash password using 8 rounds to generate Salt
bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);

Session & Cookies

Session State, which on the very general level is a kind of dictionary container, that keeps data in the memory on the server side, very often is used with Cookies, which are very small files persisted on the client (browser) side. The idea here is that when you are connecting to the server, it generates an ID for your session, which your browser is storing on the cookies level so that it is sent with each request to the server. This way, the server can recognize if the request has already been authenticated, or not. I think that’s the most popular approach so far, which has now a good alternative, that I will describe shortly. If you open a connection to my .NET videos website, you could see in your cookies such entry:

connect.sids%3AxZ_7ji543qBsWY3NgN-WFORLod

which is because I am using in my application the session state on the express side as I mentioned in one of my previous posts.

Tokens based approach (JWT – JSON Web Tokens)

Introduction

Different approach than session state could be to use JWT, which translates to JSON Web Token, and the approach is often referred to as Token based authentication. The main difference in this case is that instead of keeping the state on the server, the information about user are sent in a token on each request to the server, which verifies the user on the basis of the data included in the token. Sounds like it adds some performance penalties and is vulnerable for attacks? Not really.

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. Reading the abstract from this specification:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.

The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

Sounds better already, so you can sign JWT using a secret (with the HMAC algorithm) or a public/private key pair using RSA. This already brings some safety to the process as even if the token is modified on the client side, it won’t be validated as the signature won’t match. This means also that it’s not very risky to send the token in an URL, which you can obviously do as JWTs are meant to be compact. Obviously if you want to put it in a HTTP Header there’s nothing preventing you from doing that as well.

Construction

How does a JWT look like? It consists of three elements, which are concatenated in one string, using a dot ‘.’ The three different parts are:

  1. Header
    Header is used to define what kind of token is being sent and how is it defined. So this most probably will look like

    {"typ":"JWT",
     "alg":"HS256"}
    

    The header is then Base64Url encoded so it results in value

    eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
  2. Payload
    Payload is where the content of the token is stored. The content is a set of key/value pairs that are describing the entity (your application user) with some metadata possible. These key/value pairs are called claims.Obviously there are some reserved claims that you shouldn’t override, like
    – exp for expiration time
    – iss for issuerThe specification also defines public claims, which can be defined in a public registry.
    Private claims, are to be agreed between the parties that are exchanging the messages. If you are the one that communicates from the client and you’re the one that reads the values on the server side, of course you can use whatever you like, but adhering to the standards allows you open your API to the web in the future and make sure nothing will break or cause any problems.The claims definition is defined in section 4.1 of the official standard specification. An example payload could look like:

    {"iss":"joe",
          "exp":1300819380,
          "http://example.com/is_root":true}

    The payload is also Base64Url Encoded, so it results in:

    eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
  3. Signature
    The signature is based on the two previous parts. It takes the encoded header, encoded payload and signs it with the algorithm provided in the header. Computing the MAC of the encoded Header and encoded Payload with the HMAC SHA-256 algorithm and base64url encoding the HMAC value yields this encoded JWS Signature:

    dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

    Concatenating these encoded parts in this order with period (‘.’) characters between the parts yields this complete JWT (with line breaks for display purposes only):

    eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
     .
     eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
     cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
     .
     dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

    Benefits

  • One of the first, obvious benefits is that it doesn’t require the session state on the server side, which for many people may be very interesting option as it adds to the server side scalability. Stateless applications are generally speaking more performant and more scalable, this topic has already been described a lot on the internet, but just to bring up few benefits:
    1. Reduces memory usage. Imagine that google keeps session information about every one of their users.
    2. Easier to support server farms. If you need session data and you have more than 1 server, you need a way to sync that session data across servers. Normally this is done using a database.
    3. Reduce session expiration problems. Sometimes expiring sessions cause issues that are hard to find and test for. Sessionless applications don’t suffer from these.
    4. Url linkability. Some sites store the ID of what the user is looking at in the sessions. This makes it impossible for users to simply copy and paste the URL or send it to friends.
  • Since the token includes in the payload all the information about user, and the server knows that it’s the right information as it can verify the signature, there is no need to query the database for the user data, it’s all there.
  • CSRF brings another point to the discussion about JWTs as not relying cookies makes things much easier. You could pass your CSRF in the xsfrToken JWT Claim:
    "xsrfToken":"d889714c-1ac0-42e0-8696-2dae95dbc33e"
    
  • From a developer perspective, a nice thing is that there is a library to handle JWT for most of the languages you would use, along with a kind of online debugger, you can check it on https://jwt.io/
  • A lot more benefits that is hard to enlist could be found on the web, one of the good resources being this Auth0 blog post

.NET Videos

In my website, I started with session state, but now I am convinced to change the approach to JWT. There’s even a library (open source) to handle JWT for Angular2 by Auth0, you can check it on their github repo. Since that is the work in progress, which takes me a lot of time to understand and dig into, this is not going to see the daylight before the end of DajSięPoznać, but I will do this afterwards as I plan to continue the project. Stay tuned.

2 thoughts on “JWT vs Session Authentication

  1. Pingback: dotnetomaniak.pl

Leave a Reply

Your email address will not be published. Required fields are marked *