In a microservice architecture, the backend is made of many loosely-coupled parts. As each part is less dependent on the other parts, failure on one specific part is theoretically not bringing the entire system down.
Loose-coupling, i.e., no single point of failure is one of the benefit of microservices over a monolithic architecture.
One important concept to understand though, relatively to the loose-coupling property, is that a backend which is spread among several servers doesn't necessarily mean it is a microservice architecture. Indeed, if most of the services are still dependent on one or more service, the system is not loosely-coupled and thus can be still be considered monolithic. On the other hand, a backend composed of loosely-coupled services running on a single server can be considered a microservice architecture as communication between services is null or limited and possibility only uni-directional.
In a nutshell, loosely-coupled services limit communication among themselves. The added benefit is that the work load generated from clients can be spread among different services instead of concentrating it on a single monolith.
Authentification is one important task that each service need to perform in order to grant or deny data access. Let's see how traditional session-based authentification systems work and how a stateless solution is needed in a microservice architecture.
Session-based authentification
In a session-based authenfication scheme, a session id is a string of characters referencing a user and its associated permissions. For each request, the client provide a session id and the system then finds who is the referenced user and if it is allowed to perform the request.
This session-to-user map is probably stored in a database, but ultimately an authentification service is responsible to give the corresponding user for each provided session id. As each request reaching a service needs to be authenticated by mapping the session id to the user and its permissions, the authentification service will constantly get called by all other services. The system thus lose its loosely-coupled property and the authentification service becomes a single point of failure. In other words, the system is stateful. By retrieving the state of a user the system loose its stateless property as well.
Stateless authentification
It is now understood that traditional session-based schemes are not suitable for microservice-based architectures.
What about if it would be possible to infer the user and its permissions directly from the session id?
What about we could pass the user and its permissions by value instead of by reference ?
With this architecture there would be no need to constantly chat with the authentification service; the system would keep its loose-coupled property. The session id would become data by itself instead of a random string referencing a user.
But there is a big problem to this solution as services cannot just trust client inputs: each request can potentially be malicious and cannot be trusted.
Signing and verifying tokens
The solution to this problem involve the backend signing a part of the super session id to ensure it has not been forged on the client-side. The signature can be produced with a shared secret or with a private key.
This scheme has been standardised and the super session id is called a JSON web token (JWT). A JWT is composed of 3 parts: header (encryption type), payload (user and permissions) and signature. The resulting JWT looks similar to this string: hhhhh.ppppp.sssss
.
Here is an excellent presentation about JWT: