JSON Web Tokens

json.jpeg

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 encapsulate everything the server needs to serve the request, and thus, allow modern developers to use cookies without having to store state on the server.
  • 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.

The best approach is to store your tokens on the front-end in HTTPS-only cookies and never in local storage. This ensures that you don’t expose your tokens to the JavaScript environment in the browser which is vulnerable to XSS attacks. This also ensures that you are transmitting your tokens securely, preventing possible man-in-in-the middle attacks. To achieve this, make sure that your cookies are using the ‘HttpOnly’ and ‘secure’ flags at all times. Doing this in combination with MVC-specific protection methods ensures that you are also protected against cross-site request forgeries (CSRF). In the Backbone MVC, for example, you would use the ajaxPrefilter method and attach the token to a “csrfToken=“ string to achieve this.

But if the cookies are ’HttpOnly’ then how can we use JavaScript to let our MVC access some of the authorization information in the token so that we can render only the components that the user should have access to (without having to get that info from the server with another request)?. The solution is to put parts of the payload of the JWT into the response from the server. The parts you expose should only help guide your MVC on what to render, and should not be anything sensitive. You should still be doing the normal token authentication/authorization flow on the back-end on every request.

Hope this has been helpful! Long live single-page RESTful apps!