JWTs (JSON Web Tokens) provide an easy and scalable way to perform user access control. JWTs are often used in microservices. As shown in the diagram, JWTs are signed by an authentication server, stored by the user, and can be validated by one or more application servers when a user makes an API call.
The application server typically checks whether the JWT is valid by checking the signature, and also checking whether the JWT’s expiration date is not later than the current time.
Besides these validation checks, there’s no easy way to invalidate a JWT. Once a JWT is signed and sent to the user, the JWT can be used to send requests to the application server. The problem we want to address now is: what if the JWT is stolen, or the user wants to log out immediately?
We need to have a system where we can immediately revoke (invalidate) the JWT. We’ll need to check every call whether the JWT is not on our revocation list. Implementing a system that handles the immediate revocation of a JWT can be cumbersome and quite complex in your architecture as it increases the processing overhead of a request and thus increases the request time of every API call. Luckily, with the help of Envoy, it is possible to decrease this overhead while still checking every request to see if the JWT is revoked. Envoy proxy was built for speed and has a low footprint. In the architecture diagram below you can see how we implemented Envoy as an authorization service (Authz).
In the example above, we’re using Amazon Cognito to issue our clients a JWT. We are not using any other AWS features (like the ALB integration), because it was not feasible for our use case. When the user sends an app request, it’ll go through the Envoy proxy. For every request, Envoy will check with the authorization server, whether the request is authorized to go through. The authorization server can respond with an OK or Permission denied. If the request can go through, the authorization server can also optionally add extra data to the request, for example, to provide the application server with headers for extra authorization information.
If the application server wants to revoke the JWT before it expires, it can publish a message to the Kinesis Stream. That message will then be picked up by the authorization server and added to its internal cache. When a new request comes in, the authorization server can compare the incoming JWT to its cache, and send permission denied if the JWT matches.
This is just a simple example of how an authorization server can be used. There are many more use-cases for authorization servers in conjunction with an Envoy proxy.