JSON Web Token (JWT) have come in to my life. I like them and you will too… Pronounced “jot”, the short version is that they are cryptographically signed blobs of JSON. They pass data around that can be viewed, but not tampered with.
The longer version is that they are an open standard (RFC 7519) that “defines a compact and self-contained way for securely transmitting information between parties as a JSON object”.
JWTs look like:
If we were to split that on the “.”, we get:
1 2 3
The first string is a JSON header with details about the JWT, the second the JSON payload, the data we care about, and the third is a signature, a hash of the header, the payload, and some secret that can be used to verify that JWT as a whole hasn’t been tampered with. All are encoded using Base64URL.
Given a Ruby hash (or anything the response to to_json):
I can create a JWT using:
The token can now be shared, but not changed. It’s contents can be viewed by decoding the JWT:
true is the verify argument, and we are using the options
has to specify what hashing algorithm we are expecting (see below).)
JWTs decode as an array that contains the payload as the first element and some header information about the JWT as the second:
1 2 3 4 5 6 7 8 9 10 11
So, your payload is
It’s important to understand that the JWT is not encrypted, you can use a blank password and set verify to false and read it:
JWTs aren’t for keeping secrets. There’s another standard JSON Web Encryption (JWE) for that, we’ll look at another time.
What are they for? Authentication and safely storing state information. If I pass a JWT with the above payload to client, and it passes it back, I can verify that it hasn’t changed, so I can trust the user_id, I set it after all.
How do you use it? I’ll cover that next time!
But, before I go, we need have a little talk about security.
Notice the JWT header above includes the signing algorithm, HS256. This can be detected by the JWT library and used when decoding.
However, it’s bad form to depend on this.
One early attack was to generate a new, unsigned JWT (
'NONE') and pass that back to the app. Libraries would ignore the
password when decoding an unsigned JWT and it would appear to be
valid. Most libraries now detect this condition (using a password with
NONE) and raise an error. However, there are other possibly attacks
that work by subverting the expected algorithm, so always specify the