All Posts

JWT - Under the Hood

A computer screen featuring code

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
  • You are familiar with at least one modern programming language

No knowledge of a specific programming language is required as we will be discussing theory only without utilizing any code examples in a specific language.

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 peel back a few layers of that onion.

Compact and self-contained

A JWT is typically very small and only marginally larger than the original data being represented. It also contains all information needed to be de-coded except the key which we will discuss shortly.

JSON Object

The core of a JWT is a plain old JSON Object, there is no frill or extra syntax to learn. You just have to remember three simple parts.

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 and every bit of data is a safe bet, we’ll discuss a few caveats soon.

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

A JSON Web Token

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

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:

  • JWT.io - Tools and training for working with JWTs
  • RFC7797 - The official RFC / specification for the JWT standard
  • Node.js API Authentication with JWT - A YouTube tutorial on building a full authentication system using Node, JWT, Passport, and JavaScript by Traversy Media

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.