There are multiple ways to allow a service to be used securely. JSON web tokens is one of them, although there are limitations to the security that JSON web tokens provide. JSON Web tokens(JWT) is a standard for representing claims securely between two parties. It is quite secure because the JWT can be signed using a secret or public/private key.
What is a JSON web token?
The JWT has three parts separated with dots. These parts are the header, payload and signature. So it will look like this ‘xxxxx.yyyyy.zzzzz’. The header could look like this:
With ‘alg’ meaning the algorithm for hashing or encryption. The header will be encoded separately.
The payload contains the claims which are statements about an entity. There are reserved claims that are predefined and can be used by anyone, like exp (expiration date) and sub (subject)
let exp = Math.floor(Date.now() / 1000) + secondsBeforeExpiration
The signature is the last part of JWT and takes the encoded header and payload, and signs these using the algorithm and secret. This is shown in pseudo code below:
let signature = RS256Algorithm(encode64(header) + "." + encode64(payload) , secret);
To create the full JWT:
let jwt = encode64(header) + "." + encode64(payload) + "." + signature;
The JWT will look like this:
To use the JWT you get from a server the client should add the JWT in the header of a request like this:
Authorization: Bearer :token:
So to conclude this very brief introduction of JWTs we have an encoded message with an encrypted signature which can not be changed, otherwise the payload and header will lead to another signature.
This built-in security makes it very hard for others to generate a valid token, which can only be done by somehow guessing the secret correctly.
A possible weak spot in JWT is that you can change the algorithm from RS256 to HS256. In this case the public key will be used for verification because the signature is compared to a HMAC of the token where the public key is used as the secret. So you should verify the ‘alg’ value in the token with the algorithm on the server. In the following links you can find more information.
How to use JSON web tokens?
So what could an architecture using stateless JWT’s look like? A very simple example is given below.
You have three services (S1, S2, Auth) with one service (S1) that wants to consume the output of the other service (S2). There is also an authentication service (Auth) that manages tokens and allows requests for a token. A token will be requested at the authentication service by S1, which allows an update of data in S2. S1 will identify itself, and the authentication service knows it can provide the token to S1 for updates and create calls on S2.
But what do we win with tokens in this architecture? Firstly, we now know that the server gained a token with a claim that is valid and not tampered with. In this case a claim that gives access to perform an action on another service. The token does not contain a reference to any data on the server but contains the data itself. A problem is that the data in the token can go stale due to changes in the web application, for example when the access rights for the token owner are revoked on the authentication server, but the token will still be accepted by the services.
The tokens have a short time till they expire, so in this short time the server S1 is able to do certain requests to S2. Expiration is needed so S1 needs to acquire a new token at certain moments, preventing said problems of stale data. S1 is free to do as many requests as possible till the token expires. In this case the token itself cannot be revoked before expiration because the server does not keep track of it.
This example of the so called stateless JSON web tokens shows it can play a specific role, but the fact that they are out there and untracked is often a problem. It useful to serve in a short time span and with predefined actions that are accessible the whole time span.
Something like a short online auction where each user gets a token to be allowed to do a bid call on the server for, let’s say, 20 minutes. Making sure the token does not fall in the wrong hands would still be a problem to solve, but JWT makes sure the client bid data is not meddled with.
A nice thing about stateless JWTs is that you can do local authentication which prevents an extra call. You just provide the secret to your load balancers, for example. They all can validate the token and the client can easily switch.
So JWTs that are tracked by a server behave actually much like sessions and you should ask yourself if you want to use them. Something to take into account is that JWTs will be quite big compared to a session id, so this means bigger calls. JWTs were brought as a stateless authentication solution and here it gets really interesting that this is possible, yet often this is not what you want.
There are some excellent blog posts about the problems with stateless JWTs.
To conclude, there are good frameworks for authentication which will use JWTs themselves, and you probably don’t need to implement your own authentication service. For example, the open source Keycloak solution or LoginRadius solution both support JWTs and also other identity functionality. But when you want to implement some solution yourself, take into account that JWTs can be a stateless solution, but often you don’t need stateless authentication token or it’s safer not to have such a solution.