JSON Web Tokens
I’d like to thank the people at Stormpath/Okta for introducing me to JSON Web Tokens (JWT) and for providing a lot of great documentation for this protocol. JWT is a great authentication mechanism that is growing quickly in popularity, especially in single-page applications. JWTs give you a structured and stateless way to declare a user and what they can access, which is perfect for RESTful architectures. Some of the virtues of JWT:
- They are also a great way to declare information about the token and authentication—using JSON allows for a lot of structural flexibility and ease of use.
- They are compact, allowing for faster transmission
- They are self-contained, meaning you won’t need extra DB queries since JWTs contain all of the required info about the user already!
But wait, what’s wrong with just using the good-ol’ session-IDs that we are so accustomed to? Well, as I highlighted above, with session-ID based authentication you are pretty much forcing the server to do all of the heavy lifting while the front-end just passes around a session ID string. This is not RESTful at all, as the server has to persist the state, which leads to extensive memory usage and is bad for scalability. Token-based authentication such as JWT solves these problems by putting all of the necessary state information into the token string itself, which is checked on every request to the server. The payload of such a token usually contains: who the person is, what this person can access with this token, when the token expires, and who issued the token.
How a JWT works
The JWT has three parts: header, payload, and signature. The header describes the token. The payload has all of the ‘claims’, such as: issuer, expiration, authorization scope, and user identity. The JWT header and payload are Base64 encoded and come with a signature hash, which can be used to verify the integrity of the token if you have the secret key that was used to sign it. The signature is used to verify the sender of the token and to ensure that the message wasn’t changed in any way. To create the signature, you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
Typically, the user will login using credentials, and each subsequent request will include a JWT, allowing the user to access routes, services, and resources which are permitted with that token. The JWT is issued by the server, signed with a secret key, and is then stored on the client for use in subsequent requests. Whenever the user wants to access a protected route or resource, the request will contain the JWT, typically in the ‘Authorization’ header using the ‘Bearer’ schema.
Some best practices
If you want to implement a state-less system of expiring user sessions, then you will probably want to split the JWT logic into access tokens and refresh tokens. The access tokens will still control what the users have access to but will now also rely on the existence of a longer-living refresh token. This two token system allows for much more secure systems that issue new tokens more frequently (sometimes even on each new request) while keeping the length of the session information in a different token.
Hope this has been helpful! Long live single-page RESTful apps!