How To Validate a JWT Token

Muhammad Danyal
DataSeries
Published in
7 min readApr 14, 2020

JWT stands for JSON Web Token. It is a security validation mechanism widely used now a day. JWT is basically a string of random alphanumeric characters. There are three parts of a JWT separated by dots, header, payload, and signature. A JWT looks like this

What do I need to validate?

You see why it’s called JSON web token. It is composed of JSON objects, which are base64url-encoded and joined together as a string separated by dots. Anyone in possession of JWT can decode it and see the content. JWT tokens are digitally signed (the signature part) using the payload content and a secret key. In order to change the content, the secret key is required to generate the signature again, otherwise, the signature will be invalid. When a token is posted to the server, it must be validated to check if anyone has tempered the token or not. Lack of proper validation can cause serious security issues and here we will see how to properly validate a JWT.

In order to validate a JWT, you must know the content of JWT.

Header

The contents of the Header describe the cryptographic operations to the JWT data. This means that the header contains the information about the type of the token and the algorithm used to generate the signature (yes there are more than one and we will discuss most commonly used). So in the example header, we have a JSON object which contains a type property ‘typ’ and the algorithm property ‘alg’ whose value is the algorithm used to generate the signature. They type property says that it is a JWT token, which is our very first check to validate if the value is JWT or something else. This property is optional but since we are discussing all the possible options to be secure, we can check if this property is available, its value should be JWT. Another property “cty” (content type) is used to convey structural information about the JWT.

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

Payload

The payload is the central part of the JWT which contains verifiable security statements, such as the identity of the user and the permissions they are allowed. The payload information is also referred to as Claims. There are three classes of JWT Claim Names:

1. Registered Claim Names

2. Public Claim Names

3. Private Claim Names

Registered claims are the predefined claims. Public claims can be any user defines information and private claims are the ones upon which producer and consumer of JWT are agreed to use some special or private claims.

In order to validate a JWT, we should check some registered claims as well. Some of the important registered claims are defined below.

“iss” (Issuer) Claim

The "iss" (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The "iss" value is a case-sensitive string containing a URI value. The use of this claim is OPTIONAL. We should validate that the issuer is a valid URL or JWT is sent by out expected issuer.

"sub" (Subject) Claim

The "sub" (subject) claim identifies the principal that is the subject of the JWT. The claims in a JWT are normally statements about the subject. The "sub" value is a case-sensitive string containing a URI value. The use of this claim is OPTIONAL.

"aud" (Audience) Claim

The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected. In the general case, the "aud" value is an array of case-sensitive strings, each containing a URI value. The use of this claim is OPTIONAL.

"exp" (Expiration Time) Claim

The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim. Its value MUST be a number containing a timestamp value. The use of this claim is OPTIONAL.

"nbf" (Not Before) Claim

The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Its value MUST be a number containing a Numeric Date value. The use of this claim is OPTIONAL.

"iat" (Issued At) Claim

The "iat" (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing Numeric Date value. The use of this claim is OPTIONAL.

"jti" (JWT ID) Claim

The "jti" (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The "jti" claim can be used to prevent the JWT from being replayed. The "jti" value is a case sensitive string. The use of this claim is OPTIONAL.

Signature

The third part of JWT is the signature. This is the most important part of JWT validation. As we have already seen that signature is generated using payload and a secret key, anyone who is in possession of this key can generate new tokens with valid signatures. you have to be sure that the data in that payload is legitimate and can be trusted (at least as much as you are sure your secret key is really secret).

Most commonly used crypto algorithms used for generating signature are

· HS256 algorithm, which is short for HMAC-SHA256

· RS256 signing algorithm, which is short for RSA-SHA256

HS256 (Symmetric Key encryption) involves a secret key that is shared between two parties. This secret key is used to encrypt the data and on the receiving end, the same key is used to decrypt the data. HS256 signatures are generated using a secret key which is validated at the receiving end (resource server). On the receiving end, using the payload and secret key signature are generated again and compared to the incoming signature part of the JWT. As only the authentication server and the resources server are in possession of the secret key, it is not possible to temper the JWT token, and that’s how we can check the validity of the JWT token.

Something is wrong here

A disadvantage of the HS256 algorithm is that the secret key needs to be accessible both when generating and validating tokens. For a monolithic application, this isn’t so much of a problem, but if you have a distributed system built out of multiple services running independently of each other or same cloud environment having multiple application nodes, you basically have to choose between two really bad options:

  • You can opt to have a dedicated service for token generation and verification. Any services that receive a token from a client need to make a call into the authentication service to have the token verified. For busy systems this creates a performance bottleneck on the authentication service.
  • You can configure the secret key into all the services that receive tokens from clients so that they can verify the tokens without having to make a call to the authentication service. But having the secret key in multiple locations increases the risk of it being compromised, and once it is compromised the attacker can generate valid tokens and impersonate any user in the system.

RS256 (Asymmetric Key encryption or Public Key encryption) involves two keys, a public key, and a private key. The private key is used to generate the signature whereas the public key is used to validate the signature. In this case the private key is only in possession of the authentication server who has generated the JWT token and we no longer need to distribute the private key. On the resource server we can validate the token by using the public key. Both keys are non-interchangeable, one can only be used to generate and other can only be used for validation.

JSON Web Key Set (JWKS)

One question arises that how we can get the public key. The JSON Web Key Set (JWKS) is a set of keys that contains the public keys used to verify any JSON Web Token (JWT) issued by the authorization. Most authorization servers expose a discovery endpoint, like https://YOUR_DOMAIN/.well-known/openid-configuration. You can use this endpoint to configure your application or API to automatically locate the JSON Web key set endpoint (jwks_uri), which contains the public key used to sign the JWT .

Be more secure

By applying all these things, your web security is rock solid. Here are some extra tips which you can apply to be more secure.

  1. Verify that the JWT contains at least one period ('.') character.
  2. Let the Encoded Header be the portion of the JWT before the first period ('.') character.
  3. Base64url decode the Encoded Header following the restriction that no line breaks, whitespace, or other additional characters have been used.
  4. Verify that the resulting octet sequence is a UTF-8-encoded of a completely valid JSON.

Finally, note that it is an application decision in which algorithms may be used in a given context. Even if a JWT can be successfully validated, unless the algorithms used in the JWT are acceptable to the application, it SHOULD reject the JWT.

--

--