Prefer a video? I gave a talk on this topic at CNCF Seattle: https://www.youtube.com/watch?v=7ybmox6KQ8c
JSON web tokens (JWTs) are prevalent in modern web applications. They are used to store authentication and information about a user. They offer a convinient way to see that a user is authenticated, but they may be overkill in some use-cases. In this blog I'll outline what JSON web tokens are and some common pitfalls to avoid.
A Real Life Comparison
Let's start things off by talking about some physical world comparisons. If you have ever visited a bar you may have been asked for a form of identification before you could enter the bar and enjoy its facilities. Most likely you presented the bar security with your drivers license or passport. This piece of ID was created by an authority that the bar trusts such as the government or the department of motor vehicles. When this identification was created it was marked with special anti-forgery indicators that only the government that created it can easily produce. Once the bar security sees that they can trust this ID, next they will read the information written on the ID, such as your name and birthdate. Finally, they will check if this information meets their expectations, to confirm you can enter the bar. This process is actually quite similar to using a JSON web token. The ID is the JWT itself, the government organization that created the ID is similar to the JWT signer, and the bar security is the relying party that verifies a JWT before performing some action.
What is a JWT?
Yet another acronym in tech, what actually is a JWT? JWT stands for JSON web token, which is a direct name indicating the format of the token and where it is typically used.
JSON or "JavaScript Object Notation" is the format of a decoded JWT. If you're a web developer this should be familiar as it is a standard way to send information between a server and client. JSON lets you encode the fields of an object in a way that can easily be read and decoded.
The Components of a JWT
So what does a JWT actually look like in reality? Well, it's a long esoteric string of random looking numbers and letters like you see here. When JWTs are being sent across the network they are sent in this form. This is 3 segments of JSON information base64 encoded separated by dots.
What is a Signature?
There are 2 ways you can sign your JWTs to assure their validity, symmetrically and asymmetrically.
Symmetric Signing
Asymmetric Signing
The JWT Lifecycle
JWT Validation
Let's create some pseudocode with our steps to verify a JWT given our current knowledge.
- Separate the encoded JWT into its 3 segments.
- Decode the header and payload.
- From the header segment check which signature algorithm to use.
- Verify the signed hash matches the hash of the header and payload.
- Check if the JWT is expired.
- JWT is valid. Check if the user is authorized to perform their requested action based on the values in the JWT payload.
Signature Algorithm Confusion
Secret Brute Forcing
Store your JWTs Securely
An increasingly common attack vector recently has been to steal or intercept a user's JWT directly rather than stealing their username and password. As 2FA is becoming more common, directly stealing the JWT allows the attacker access for the lifetime of the token without having to worry about getting the victim to approve a 2FA request.
Protect your Secret Key at all Costs
Even worse than an individual JWT being stolen would be the secret key of the JWT issuer being stolen. If this secret key is compromised then an attacker could create tokens with any authentication information they desire and these tokens would be accepted by any service that trusted this key!
You Might Not Even Need JWTs
As we have covered, JWTs are great for simple authentication and information about users in distributed systems, but that doesn't mean they are always the solution to your authentication problems. If you can use a standard stateful session token that is simply looked up in a database that may be the ideal way to handle authentication in your scenario. It's much easier to revoke stateful session tokens as it just means updating a row in the database. You can also easily update information associated with the token in the database. Make sure that the tradeoffs of statelessness are worth it in your scenario.