Skip to main content

Understanding JSON Web Tokens (JWT)

Introduction

JSON Web Token is known as JWT. It is an open standard that is used for transmitting information between parties as a JSON object. JWT is a secure way for Authentication and Authorization because it is digitally signed. It can be secured by using a secret key or a public and private key with applying different types of algorithm. It is supported by most of the application like .Net, Java, Python, PHP, Ruby, JavaScript, Node.js and etc. JWT can be used as a query string, cookies, HTTP header or body parameter. This is a very useful way for single sign-on (SSO).

Structure

JWT consist of three major parts:

  • Header
  • Payload
  • Signature

These three parts are separated by dots (.) and all are in Base64Url encoded format as below

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3ZpdmVra3VtYXIuY29tIiwiaWF0IjoxNTQ0MDM0Mjg3LCJleHAiOjE1NzU1NzAyODcsImF1ZCI6Ind3dy52aXZla2t1bWFyLmNvbSIsInN1YiI6InZpdmVrQHZpdmVra3VtYXIuY29tIiwiTmFtZSI6IlZpdmVrIEt1bWFyIiwiUm9sZSI6IkFkbWluIn0.JCiVwlHWrgxZHrdGjGdlMH7rMij2Atd6rw0C7reVnd8

Header

It usually consists of two parts

  1. Typ – generally it will be JWT
  2. Alg – hashing algorithm

In the above token, the header is the first part before the first dot (.), which is in Base64Url encoded format as below.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

When we will decrypt Base64Url above header then we will get JSON like below

{

  "typ": "JWT",

  "alg": "HS256"

}

 

Here “typ” is used for identifying the token type which will generally JWT and “alg” is used for identifying the hashing algorithm which is involved in creating a signature for JWT.

Payload

In the above token, the Payload is the second part, between the first and second dot(.), which is also in Base64Url encoded format as below.

eyJpc3MiOiJodHRwczovL3ZpdmVra3VtYXIuY29tIiwiaWF0IjoxNTQ0MDM0Mjg3LCJleHAiOjE1NzU1NzAyODcsImF1ZCI6Ind3dy52aXZla2t1bWFyLmNvbSIsInN1YiI6InZpdmVrQHZpdmVra3VtYXIuY29tIiwiTmFtZSI6IlZpdmVrIEt1bWFyIiwiUm9sZSI6IkFkbWluIn0

Payload contains the claims. Claims are the statements about an entity, generally user and also it contains additional metadata.

There are three types of Claims.

  1. Registered Claims
  2. Public Claims
  3. Private Claims

Registered Claims: These are a set of predefined claims which are recommended and we have to use it while creating the token, some of them are very useful while validating the token by other service but it is not mandatory.

Below is the example of registered claims:

  • iss (Issuer): It identifies the principal that issued the JWT. Generally a DNS name.
  • sub (Subject): It identifies the principal that is the subject of the JWT. The subject is unique in the context of the issuer. It is generally user id or email id in the context of the user.
  • aud (Audience): It identifies the recipients that the JWT is intended for. In the general case, the “aud” value is an array of case sensitive strings, each containing a StringOrURI value.  In the special case when the JWT has one audience, the “aud” value may be a single case-sensitive string containing a StringOrURI value.
  • exp (Expiration Time): It identifies the expiration time on or after which the JWT is no longer valid.
  • nbf (Not Before): It identifies the time before which the JWT must not be accepted.
  • iat (Issued At): It identifies the time at which the JWT was issued
  • jti (JWT ID): It is a unique identifier for the JWT, basically we can say it is identity key of each JWT.

Public Claims: These can be defined at will by those using JWTs. However, in order to prevent collisions, any new claim name should either be registered in the IANA “JSON Web Token Claims” registry or a value that contains a Collision-Resistant name. In each case, the definer of the name or value needs to take reasonable precautions to make sure they are in control of the part of the namespace they use to define the claim name.

Examples of collision resistant namespaces include:

  • Domain name
  • UUID

Private Claims: These are the custom claims, a producer and consumer are using for sharing the information. These claim names can be any things except registered claims or public claims.

 

If we decrypt Base64Url of above Payload, then we get JSON like below

{

  "iss": "https://vivekkumar.com",

  "iat": 1544034287,

  "exp": 1575570287,

  "aud": "www.vivekkumar.com",

  "sub": "vivek@vivekkumar.com",

  "Name": "Vivek Kumar",

  "Role": "Admin"

}

Signature

In the above token, the Signature is the last part after the second dot(.)

JCiVwlHWrgxZHrdGjGdlMH7rMij2Atd6rw0C7reVnd8

Signature is responsible for validating the JWT.

To create the Signature part, we need the encoded header, the encoded payload, and a secret. Now we can use an algorithm to create a signature. Either we can use one secret key known as symmetric cryptography or we can use Public-key cryptography known as asymmetric cryptography for signing. It’s totally up to us which algorithm we are going to implement to create a signature

Below is some algorithm which is used to create a signature

  • HS256
  • HS384
  • HS512
  • RS256
  • RS384
  • RS512
  • ES256
  • ES384
  • ES512
  • PS256
  • PS384

In this above token, we are using HMAC SHA256 algorithm known as HS256 (symmetric key algorithm) so for that we have to use following way

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Now we dig it more so that we can understand it in the more easy way.

First, we combine the encoded header and encode payload as below

encodedHeaderPayload = base64urlEncode(header) + “.” + base64urlEncode(payload)

 

Now we use hashing function as per our choice. hashedData = hashFunction( encodedHeaderPayload, secret ) In this example, a secret is a string which we want to pass for encryption. Now the final part is converting the hashedData into base64urlEncode format as below.

signature = base64urlEncode(hashedData)

 

So putting all three components together as below

header + “.” Payload + “." + signature

 

We can use https://jwt.io to see JWT header and payload information and also we can verify it like below

Understanding JWT

 

When to use symmetric key algorithm and asymmetric key algorithm

Symmetric key algorithm: If we want to create a token and want to verify by us only at that time we can use symmetric key algorithm that means authentication server and application server are same.

Asymmetric key algorithm: If we want to allow third party application to verify our token, we can use asymmetric keys and share the public key with the third parties. As public keys cannot be used to sign so that no one can forge a valid token with custom claims. The way we share the public key is up to us.

Example: Google keys at https://www.googleapis.com/oauth2/v3/certs

How do JSON Web Tokens work

First of all, If a user wants to get a JWT then the user has to provide their credentials as a part of authentication and after successful logs, JWT will be returned.

Now, whenever the user wants to access a protected resource from the server then the user agent sends the JWT generally, it is in Authorization header using the Bearer schema.

The content header looks like below

Authorization: Bearer <JWT>

 

JWT is a self-contained way for securing transmitting information between two parties so it’s a stateless authentication mechanism. Generally, it contains all the necessary data so we don’t need to call the database.  Mostly we use Role or Scopes in the payload to access the protected resources.

There are many open source libraries to support JWT in most of the languages such as .NET, Java, PHP, Python, Ruby, Go, Scala, Swift, C, C++, JavaScript and etc.

Conclusion

In this article, we got the understanding of JSON Web Tokens (JWT) and its benefits.

We can choose algorithm as symmetric key algorithm or asymmetric key algorithm as per our requirements.

If you have any suggestions or questions, please mention them in the comments section.

2 thoughts to “Understanding JSON Web Tokens (JWT)”

  1. For assymetric key algorithm will the public key also will be shared in the signature? If not then how to share this while registering different system , like downloading the certificate first?

    1. No, we will not share the public key in the signature and also don’t need to download the certificate first.
      As I explained in this article, “The way we share the public key is up to us.” Generally, we use one of the URI to share the public key to the third parties/world so that they can validate token.
      Generally in OIDC protocol we use Discovery-document URI as “https:///.well-known/openid-configuration” and third parties will hard-code this Discovery-document URI into their application and then retrieves endpoint URIs from it as needed (e.g. – issuer, authorization_endpoint,token_endpoint,userinfo_endpoint,jwks_uri,response_types_supported and etc), Third parties application also get the “jwks_uri” value which is URI for public key information from the discovery document. but its all up to us how we share the public key to the third parties/world.

Leave a Reply