Code With Joad

Photo of Jody LeCompte

Posts about web and software development by Jody LeCompte

JWT - Under the Hood

Taking a look at JSON Web Tokens in Depth

Published April 10, 2019

A JWT is a standard for communicating a bundle of data between two parties. They are a powerful tool utilized namely in token-based or stateless authentication systems. Have you ever wondered how they work under the hood? How do they keep data secure? Let's try to answer those questions.

Prerequisites

This article makes the following assumptions:

  • You are familiar with the concepts of hashing and encoding
  • You are familiar with JSON as a data structure

No knowledge of a specific programming language is required as we won't utilizing any code examples.

10,000 Foot View

A JWT, pronounced as 'jot' is defined by jwt.io as such:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

Let's begin by breaking that down into a few atomic units:

Compact and self-contained
A JWT is typically very small and only marginally larger than the original data being represented.

JSON Object
The core of a JWT is a plain old JSON Object, there are no frills or extra syntaxes to learn. You just have to remember three simple parts we'll talk about in a bit.

Digitally Signed
The digital signature, as alluded by the explanation above, is what helps to ensure a JWT is safe. This does not mean that any data is suitable, more caveats to follow.

JWT Easy as 1-2-3

While the data of a JWT is JSON object, it is actually expressed as an encoded string after it has been packed. It is made up of three unique pieces that are separated by periods as illustrated below.

Anatomy of JWT

The first and section sections are both JSON objects that have been stringified and Base64 encoded, while the third is a hashed signature of preceding parts.

Header

The header is a simple structure that defines some metadata about the token such as it's type or the algorithm used to create it's signature. For example, if we take the first section and decode it,we receive the following value

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

This signifies that our token is a JWT and the algorithm being used for signing is HMAC SHA256. There are in theory possibly some algorithms that are not suggested, but in practice any will suffice so long as both parties agree.

You can also find other metadata such a token expiration here as well.

Payload

The payload is the actual data that the JWT is intended to share. Again represented as a Base64 encoded string. The second portion of the above JWT will decode to the following information:

{
  "display_name": "Jody",
  "user_id": 35
}

You may be asking, if the data is simply Base64, then how it is safe? Well in short, from that particular perspective, it is not safe.

This is the caveat hinted at before. The signature that we will look at shortly prevents tampering, but no data that is sensitive and should not be exposed (ie. a user password) should be contained in a JWT. Simply store whatever safe information can be used to reference this other more sensitive data later from a database, other API, or similar service.

Signature

The signature is the Key that gives the JWT most of it's power. As mentioned above, since the payload is simply Base64 encoded JSON, there is literally nothing stopping someone from intercepting and changing this JSON and trying to pass it off as an original token.

The signature prevents this by the introduction of a shared secret. It is generated by means of the hashing algorithm specified in the header, a secret key shared between any parties that need to be able to digest or re-encode a JWT, and the data payload. In pseudocode, it would look something like this.

hash(header + ' . ' + payload + secret)

So this means if someone were to tamper with our JWT, then we would know when we try to decode because the secret would not match up with what it is supposed to be and the hash would not line up properly indicating the token is invalid and needs to be revoked.

You can also use RSA encryption with a private key as well.

Stateless Authentication

In the opening post I mentioned stateless authentication and if you are new to JWTs or web development, you may be asking exactly what that means.

In the days before token based systems, one common approach was to use a combination of cookies and server side sessions to accomplish a similar goal such as maintaining a users login across page loads. The cookie would be sent with all requests and used to tie back a client user session with a backend session storing a similar set of data to the above.

JWTs and token based auth can be stateless because you do not have to persist state in some way like the above example. You don't even have to have created the JWT you are receiving. As long as you know where to look, the header, to find out which algorithm is being used and know the secret, then you can decode with no issues without needing to persist user state on the server or in the client.

Language and Platform Agnostic

The largest benefit for JWTs in my book is the fact that while they may be based on JSON which originated from the JavaScript ecosystem, you can use it almost anywhere and even between services written in different stacks / technologies. Being Base64 encoded means that it's also URL safe.

A few common tools of the trade:

Further Study

Interested in learning more? I dig it! Feel free to check out some or all of the below:

Conclusion

If you were anything like me, you may have spent a long time utilizing JWTs indirectly by means of helpful open source libraries without really understanding how they were working under the hood. I hope you feel much more comfortable in sharing the gospel of JWTs and utilizing them in your web applications and projects. As always, thanks for reading and share with your friends if you found this helpful.