Photo by Eric Prouzet on Unsplash

The Wonderful (and not so Wonderful) World of Tokens

And so a piece of magic happens for your development team …

“We can get a single token from somewhere, and that will allow us to authorize all the services for our complete infrastructure?”,

“Yes. It is truly magic!”,

“And we have to do nothing?”,

“Yes. Very little. Pass the user onto something, and add a couple of links of code in your scripts, and you don’t have to worry anymore. A simple check, and all that security stuff goes away.”,

“Wow! That is truly magic!”.

Welcome to the wonderful (and not so wonderful) world of tokens. It is a world where broken authentication and injection are two of the top security risks within many organisations. It is a world where simplicity often trumps security, and where a magic bullet makes all the security problems go away. But it is a bear trap that could bring down your whole infrastructure with a simple hack.

We are increasingly moving to a world of tokens, where we will use them to gain access and rights into systems, and where we could even define our ownership of assets with the ownership of a security token. With this, we ask for access to services, and then authentication ourselves to an authorization service, and which gives us an authentication token which can be passed to services. This leads to the opportunity to have a single-sign-on (SSO) and for us to grant access to a trusted network, without having to set up our own authorization infrastructure:

But it has many problems, as the tokens can often be copied and played back into the network. In some cases, the tokens have very little security built into them, and can easily be copied and faked. But, they are a dream for developers as they don’t have to worry about the authorization part anymore as the token can be trusted to have done that. But the trap that developers fall into is that this token is easily copied and playback into the system. A simple operation in Chrome allows the token to be seen in its raw format, and then Postman or Python can be used to play it back and gain access to privileged resources. The development team often do not check the details of the token, and for the rights that are gained from it.

So let’s look at a few examples of tokens. One of the most widely used methods is the JSON Web Token (JWTs). With this we have our claims — such as the owner of the token, the start date of the token, and the expiry date of the token — added to payload of the token, and then for it to be signed either with HMAC (with a secret key) or with RSA (using a public and a private key):

The signing process is important, as it validates that the entity is a trusted entity. For HMAC, only the authorization service will know the secret which has signed the HMAC signature. For an RSA signature, only the authorization server will have the private key for the signature, and where we can prove with its public key. What we get is a URL safe Base64 format for our token, and which is split (by the ‘.’ character for the three fields):


The 4QpsBQ5HDbAjzv3EaMp0UQdCG-MnEanW7g8q9AUvOLU part is thus the signature, “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9” is the header, and “IntcImlzc..cIn0i” is the payload body. A part of the JWT is the expiry time, and this is key to limit the scope of a hack being performed on the system with a stolen token. A typical time is one hour, and where the user would need to re-authenticate after an hour. But within that hour, an attacker can easily copy the token and then play it back against other services. If the attacker determines the secret passphrase for signing the token, they can create valid tokens and gain privileged access to the network.

JWT does not hide the data, and the payload is thus encoded and is signed, but it is not encrypted. Some simple Python code to implement JWT is defined here [demo]:

var args = process.argv;var sec=’fff’;var pay=”{ foo: \’bar\’}”;//if (args.length>1) pay=args[2];//if (args.length>2) sec=args[3];console.log(“Message:\t”,pay)console.log(“Passphrase:\t”,sec)var jwt = require(‘jwt-simple’);var payload = pay ;var secret = sec;// encodevar token = jwt.encode(payload, secret);console.log(“Token: “,token);// decodevar decoded = jwt.decode(token, secret);console.log(“Decoded: “,decoded);

There are so many cases of bad practice with JWT, especially where developers do not understand the risks of dealing with these tokens. If possible, the software with the infrastructure should also integrate session variables, and make tie the token into a session, and if possible tie against the TLS connection that is being made, so that an intruder cannot copy a token to another session.

In order to test our token access, we often use Postman, and which can use “GET” and “POST” to connect to a RESTful Web service. For JWT, we basically perform a “GET” HTTP request, and then add an “Authorization” key with the “Bearer ” and the JWT token:

While the usage of JWT is often weak, the implementation of OAuth is often shambolic. This was highlighted by a recent research paper:

Overall, the OAuth 2.0 weakness was a well-known flaw in systems, but few really wanted to highlight is, as it was just so easy to implement with. Basically, I could write an application which used Facebook as a login system and then to me to receive a token back to say that the user had been authenticated by Facebook. Unfortunately, Facebook now knows that I log into your system. But the greatest problem is it has very little in the way of security and trust. For some reason, security was dumped from the transition between 1.0 and 2.0.

With OAuth 2.0, we register an application name, an application Website, and a callback URL, and the site returns a Client ID, and Client Secret. We then pass these as parameters in the API call, and log into the trusted system, and which returns a token back to the callback URL:

The token has no real signing involved, and can EASILY be copied and played back to the callback URL. Seldom in the development of standards has a protocol moved from one version to the next, and actually make security and complexity worse.

So let’s say I want my users to login via GitHub. I would then register a new OAuth application, and then it will give me back the Client ID and Client Secret, and for the login process the user will be guided to GitHub to log in:

But we have many problems here. The first is the lack of proper security in the token, and the second is that we will now have to embedded the Client ID and Client Secret into our code. Many systems now have their code in GitHubs, and where intruders can just scan the GitHub for these secrets, and then are able to gain trusted access, and create redirects.

And so if your dev team is scratching their heads on the best way to encrypt and sign data, then point them towards Fernet tokens. With these tokens, we can use AES encryption with salt, and then derive the encryption key from a key derivation function (KDF). A typical KDF is PBKDF2, as it is a slow method of generating the key (and thus reduces the opportunity for brute force attacks). We also get an HMAC signature and which is signed by a secret, along with a timestamp:

A demo of Fernet is given [here]. A great advantage of using Fernet is that we can use key rotation. In this, we can generate a number of keys between Bob and Alice, and then change them over given periods. In this way, Eve can get confused in that the keys may change each day.

So here’s a lecture on tokens:

Broken authorization is one of the top security vulnerabilities. You — and your dev team — and everyone else involved in information security in your company MUST take it seriously, and not see it as a balance between ease-of-use and security. A breach of a trust infrastructure is one of the most expensive things to deal with, so don’t get caught out. Protect the tokens!

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. EU Citizen. Auld Reekie native. Old World Breaker. New World Creator.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store