I am studying JSON Web Tokens, and want to try making my own authentication server (don't worry, this won't run in production anywhere). My understanding so far is this: you create a JSON string that holds all the data you want, and create a hash based on this data using a secret, which you include in the JWT as well. The secret is shared between the authentication server and the application server. The application server you send your requests to uses the same secret to recalculate the hash and compares it to that in the JWT.

Now, if for some reason your application server gets compromised and the secret comes out, you are out of luck. And you might not want your users to dissect your JWT's. So I came up with this idea:

Having the authentication server encrypt the JWT with a private key, and then having the application server decrypt it with the public key means two things: clients can't inspect the contents of their JWT's, and a comprimised application server means you still can't create fake JWT's, as the private key is not yet compromised. Decrypting with the public key also means you know the JWT is from the authentication server. As far as I can tell, encrypting with the private key and decrypting with the public one, while unusual, should not lead to weaker encryption.

My question: is there something wrong about my thinking, that could lead to this kind of authentication system not working or being easy to compromise?

2 Answers
2

What you describe here is little more than a randomly generated session id, however most of the things which differentiate this from a session id are a disadvantage to your security. The one advantage is that you are storing state at the client and hence have a scalable, fault tolerant solution. But it does require rather a lot of processing to decrypt an asymmetric cypher.

However as the token contains encrypted data, you are putting your trust in the effectiveness of the algorithm and its implementation. Users will be in posession of both the cypher text and at least part of the cleartext - which is a big help in breaking the encryption.

As described, there is nothing to protect against a mitm (e.g. setting a ttl and key re-negotiation mechanism) or xss attack.

As it stands you need to be very careful with the disposition of the secret - e.g. in backups, failed disks, san images etc. Compare this with a random session id which expires with the session.

Certainly splitting the key pair (there does not appear to be a requirement for either part to be considered "public") adds some value, particularly if the authentication server is running a different software stack and not exposed on the internet.

But personally I would prefer a SSO server using established protocols (e.g. openam) and a random session id, optionally supplemented by single use tokens in local storage for tin foil hat security.

I normally don't like to say "yes this is secure", but I will go as far as to say it lookstheoretically secure to me, based on the information provided. However...

Aside from obvious things like the limit to how much data a token could contain (assuming RSA) and the fact that all your tokens would be ~256 bytes or larger (that's a lot of data to send in every single request), I don't think your system would help at all if your Application server was compromised, which I think was the original idea?

First, the compromised server could simply continue to request as many tokens as it likes from the Authentication server. Not to mention the fact that it wouldn't need to because it is the one that verifies the tokens anyway. It could simply be reprogrammed to accept any token or no token at all.

Theoretically, your system makes sense and looks secure to me, which doesn't mean much. But a compromised server is a compromised server at the end of the day!