Monolithic, Microservice Architectures and Security of JWT Tokens

efran
4 min readNov 11, 2023

Before testing a system, we need to understand what it is and why it exists. So, let’s start by explaining what a JWT (JSON Web Token) is and why there is a need for such a design.

Monolithic application design refers to the design where multiple modules are consolidated in a single location, single code base. For example, both the frontend and backend are hosted on the same server, and all functions of the application can access the database. When a user logs in, the corresponding cookie given to them is stored somewhere. Since all functions within the application can access the application’s database, queries regarding the existence and validity of the given cookie can be easily performed. If these cookies pass the checks, the user is considered as real and exist. And the relevant functions are then made accessible to the user.

So, what if we seperate the services and connect them independently as we wish? For example, imagine a bank application; a distinct service would responsible for each functions, such as user login, user logout, credit card, transaction operations and so on.
With microservices arthitecture, we would also gain advantages in scability, flexibility and agility. We can allocate more resources to the services, and allocate fewer resources ot others as neededed.

Figure 1. Monolithic and Microservice Architecture

In microservice architecture, services no longer share a shared database, and generally different microservices cannot access the same database. So how we can control user authentication in this scenario since we do not have a shared database for user auth? This is where JWT(JSON Web Tokens) comes into play. We need to determine if a request comes from a user with the correct authorization, check if the cookie in the request is valid and not expired. Due to the absence of a shared database, we cannot perform these checks with database queries.

A deletion request sent to the deletion service involves the microservice parsing the incoming token and inspecting its content, but it does not authenticate. It does not query whether the cookie is really exist or is correct. Instead, it only checks if the user in the token has th authorization to perform the action.

Now, what if an attacker manipulates this cookie value, changing the auth parameter to admin? According to the architecture described above, this operation would succeed, allowing unauth user to perform action with admin privileges. But, this situation is mitigated by cryptographic functions.
In practice, JSON Web Tokens often use cryptographic signatures to ensure the integrity of the token. If an attacker tries to tamper with token content, the signature verification wold fail, renderin the token invalid. This security measuse helps prevent unauth users from manipulating their tokens to gaing privileges.

Figure 2. JWT Token Structure

When we look at Figure 2, we understand that a JWT token consist of three parts: the header, payload, and signature.

  • In the header section, we mainly have metadata such as the algorithm and token type.
  • In the payload section, we have data that the application’s back-end will use, such as username and authorization information.
  • The signature section contains a secret key in addition to base64 encoded types of payload and header.
    When a this token is signed with a private key, it is used to verify the authenticity of the sender and ensure that the message has not changed along the way.

HMAC (Hash-based Message Authentication Code)
If we hash a message and transmit it, we can ensure that the message remains unchanged along the way, but we cannot verify its origin.

However, if we add the sender and the secret key held by the recipient along with this hash, we can prove the authenticity of the sender and that the message has not changed in transit.

Data integrity and sender identity verification are achieved using HMAC in the signature section of the JWT token.
As seen in Figure 2, the recipient can easily decode the base64 format of the header and payload, but they cannot verify and confirm the token has not been altered during the transit unless they have the secret key.

The recipient knows that the content of the message cannot be altered without the secret key. If any changes occur, the recipient will detect that the signature has also changed, making it impossible to verify. They can recognize that the message has been tampered with.

BEST PRACTICES

  • Perform Algorithm Verification
  • Validate All Cryptographic Operations
  • Always Validate Cryptographic Inputs
  • Use Strong Secret Keys
  • Do not Trust Received Claims and Validate All Possible Claims
  • Use the typ claim to seperate types of tokens

Attack Vectors/Scenarios

  1. If the developer forgot to verify the signature
  2. If the developer did not perform expiration check
  3. Can the hash inside the JWT be cracked?
  4. None algorithm
  5. Injecting self-signed JWT’s via jwk parameter
  6. Injecting self-signed JWT’s via the jku parameter
  7. SQLi, Path Traversal, Command Injection via kid parameter

The detailed explonation regarding the attack vectors and associated practives is provided in the following text.

REFERENCES
-
https://www.youtube.com/watch?v=ju-53ZyjfEA
- https://www.cobalt.io/blog/all-you-need-to-know-about-jwt-pt.-2
- https://www.cobalt.io/blog/json-web-tokens
- https://jwt.io/introduction
- https://www.invicti.com/blog/web-security/json-web-token-jwt-attacks-vulnerabilities/

--

--