Periklis Ntanasis:
Master's Touch

fade out

JWT handling in a Javascript client

On Tuesday 18 of September my coleague Christos and I decided to attend the Angular Athens #3 meeting.

There were 2 topics presented. An introductory presentation on angular navigation and routing and an intermidiate prestantation on authentication and authorization using JWT.

This post is inspired by the second presentation on JWT. The specific presentation in my opinion was very well presented by Fanis Prodromou and I really liked it.

This article is based on something that the presenter said during that talk. When the speaker was explaining how the JWT works, he mentioned that all angular libraries that he knows of require the secret key in order to decode the JWT.

He claimed that storing the secret key inside the client seems like a bad idea to him and so he justs (base64) decodes the JWT "manually", in order to get the contained information (claims).

The particular part is mentioned in this video in ~58:50 (in Greek).

So, the speaker gave us as a homework assignment to research why the libraries require the secret key.

Here I am, having made my research :-)

How JWT works

First of all let me quote the abstract of RFC 7519.

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

RFC 7519
— IETF

In other words, this means that a JWT is the medium of transportation, a JWS has the ability to validate that the JWT is not tampered by one who has not access to the signature key and the JWE has the ability to not reveal the JWT content to the parties that have not access to the decryption key.

Let me also quote the paragraph 12 from the RFC that is relevant.

12. Privacy Considerations

A JWT may contain privacy-sensitive information. When this is the case, measures MUST be taken to prevent disclosure of this information to unintended parties. One way to achieve this is to use an encrypted JWT and authenticate the recipient. Another way is to ensure that JWTs containing unencrypted privacy-sensitive information are only transmitted using protocols utilizing encryption that support endpoint authentication, such as Transport Layer Security (TLS). Omitting privacy-sensitive information from a JWT is the simplest way of minimizing privacy issues.

RFC 7519
— IETF

JWT and the browser

So, what should we do in an angular application which lives in the browser?

The JWT that Fanis used was actually a JWS and in that case we should do what he did and just base64 decode it. Of course to be sure that the content is trusted and there isn’t a man-in-the-middle attack taking place, the server should serve the content over HTTPS.

A web application shouldn’t store the signature or encryption key because the key would be exposed to everyone making it useless and actually the client do not need to validate the token as it knows that it comes from the trusted server, because of the HTTPS/TLS.

When to use and validate the JWS

I’ll oversimplify some things for the sake of brevity and because I believe that there is no need for more detail and accuracy for the topic that we are discussing.

In the case of JWS the key should be used by the web service/issuer to validate that the tokens that receives back from the client are the one that were issued by it originally.

This may work as an alternative to the traditional sessions. The server however do not have the task of maintaining the table of active sessions. It just has to validate the token and check the expiration date to see if it is valid.

In case we are talking about multiple web services that are communicating together, all may follow the previous procedure and in practice "share the user session".

Also, the token may contain (not sensitive) information that is accessed often by the server in order to avoid making pricey calls to the db.

Of course the token may contain information that is required by the client too.

However, storing too many information in the JWT introduces a bandwidth overhead, as the JWT has to be included in all the requests made by the client.

When to use JWE

A JWE may contain sensitive information that the server retrieved from the database and wants to avoid making the retrieval again in the future, in order to reply to a following request made by the client.

The server of course do not want to share all these private information with the client and that is achieved through the encryption.

Enough about all that JW*.

What about the Javascript libraries?

In the past things were simpler. Javascript was living only in the browser. Today this is no longer true. Javascript is everywhere and people are building web services in Javasctipt all the time with nodejs.

I do not remember what were the libraries mentioned by the speaker and I cannot see them clearly in the video, but I guess these libraries were supposed to be used by web service authors.

Making a search I was able to find a couple of libraries that do not required a secret key in order to decode the JWS payload:

The second one mentions pretty clearly that it is intented for client use:

Important This library doesn’t validate the token, any well formed JWT can be decoded. You should validate the token in your server-side logic by using something like express-JWT, koa-JWT, Owin Bearer JWT, etc.

Epilogue

The motivation behind my research wasn’t of course the speakers' request.

I have used JWTs just like that in the past. So, hearing that all the known libraries were requiring the key made me wonder if I was doing something wrong.

You see, the fact that all the well known libraries were using the key made me consider that this should be the right way.

Also, none from the audiense objected or volunteered to clarify after hearing this. I guess some may knew about it but were unsure at the moment or didn’t want to disrupt the presentation.

Anyway, I was happy to validate through my research that the way that the presenter demonstrated (and I use) doesn’t have any flaw.

I applaud the work of Angular Athens who try to organize events, create a network of front-end professionals and host interesting talks. All this requires precious time and effort. I also enjoyed Fanis' presentation. It requires very much effort to prepare a nice talk and speaking to an audience with many persons that you don’t know is often very intimidating.

Thank you for reading!

Comments

fade out