JWT vs PASETO
Nowadays, token-based authentication has become more and more popular in the development of web and mobile applications.
There are many different types of tokens, but among them, JSON web token (or JWT) is one of the most widely used.
However, in the past few years, we’ve also discovered several security issues regarding JSON web token, mainly because of its poorly designed standard.
So recently people have started migrating to other types of tokens such as PASETO, which promises to bring better security to the application.
In this lecture, we will learn everything about the security issues of JWT and how PASETO is designed to solve all of those problems.
Here's:
- Link to the full series playlist on Youtube
- And its Github repository
Token-based authentication
First, let’s talk a bit about token-based authentication.
Basically, in this authentication mechanism, the client will make the first request to log in user, where it provides the username and password to the server.
The server will check if the username and password are correct or not. If they are, the server will create and sign a token with its secret or private key, then sends back a 200 OK
response to the client together with the signed access token.
The reason it’s called access token is that later the client will use this token to get access to other resources on the server.
For example, let’s say the client wants to get the list of bank accounts that belong to the logged-in user. Then it will make a GET /accounts
request to the server, where it embeds the user’s access token in the header of the request.
Upon receiving this request, the server will verify if the provided token is valid or not. If it is valid, the request will be authorized, and a 200 OK
response will be sent back to the client with the list of user’s bank accounts.
Note that an access token normally has a lifetime duration before it gets expired. And during this time, the client can use the same token to send multiple requests to the server.
So that’s how the token-based authentication works.
JSON Web Token
Now let’s talk about JSON Web Token! Here’s an example of a JSON Web Token:
It is a base64 encoded string, composed of 3 main parts, separated by a dot.
The first part (with the color red) is the header of the token. When we decode this part, we will get a JSON object that contains the token type JWT
, and the algorithm used to sign the token: HS256
in this case.
The second part (in purple) of the token is the payload data. This part is where we store information about the logged-in user, such as username, and also the timestamp at which this token will be expired.
You can customize this JSON payload to store any other information you want. In this case, we also have an ID field to uniquely identify the token. It will be useful in case we want to revoke access of the token in case it is leaked.
Keep in mind that all data stored in the JWT is only base64-encoded, not encrypted. So you don’t need the secret/private key of the server in order to decode its content.
It also means that we can easily encode the header and payload data without the key. So how can the server verify the authenticity of the access token?
Well, that’s the purpose of the third part of the token: the digital signature (in blue color). If you don’t know how the digital signature algorithm works, then I recommend you to read my post about SSL/TLS before continuing.
The idea is simple, only the server has the secret/private key to sign the token. So if a hacker attempts to create a fake token without the correct key, it will be easily detected by the server in the verification process.
The JWT standards provide many different types of digital signature algorithms, but they can be classified into 2 main categories.
Symmetric-key algorithm
The first one is symmetric-key algorithm, where the same secret key is used to both sign and verify the tokens.
And since there’s only 1 key, it should be kept secret. So this algorithm is suitable for local use only, or in other words, for internal services, where the secret key can be shared.
Some specific algorithms which belong to this symmetric-key category are: HS256
, HS384
, and HS512
.
Here HS256
is the combination of HMAC
and SHA-256
. HMAC
stands for Hash-based Message Authentication Code, and SHA
is the Secure Hashing Algorithm. While 256/384/512
is the number of output bits.
Symmetric-key algorithm is very efficient and suitable for most applications.
However, we cannot use it in case there’s an external third-party service that wants to verify the token, because it would mean we must give them our secret key.
In that case, we must use the second category: asymmetric-key algorithm.
Asymmetric-key algorithm
In this type of algorithm, there’s a pair of keys instead of just 1 single secret key.
The private key is used to sign the token, while the public key is used only to verify it.
Therefore, we can easily share our public key with any external third-party services without worrying about leaking our private key.
Within this asymmetric-key category, there are several groups of algorithms, such as RS
group, PS
group, or ES
group.
Here, RS256
is basically RSA
algorithm with PKCSv1.5
and SHA256
.
PS256
is also RSA
algorithm but with Probabilistic Signature Scheme and SHA256
. It was designed to be more secured than PKCSv1.5
And the last one ES256
is simply Elliptic Curve Digital Signature Algorithm with SHA256
.
Problems of JWT
OK, so far it sounds like JWT is a good standard, and it gives us a lot of flexibility to choose whatever signing algorithms we want. So what exactly are its problems?
Weak algorithms
Well, the first problem is weak signing algorithms. JWT gives developers too many algorithms to choose from, including the algorithms that are already known to be vulnerable, such as:
-
RSA
withPKCSv1.5
is susceptible to a padding oracle attack. - Or
ECDSA
can face an invalid-curve attack.
For developers without deep experience in security, it would be hard for them to know which algorithm is the best to use.
So the fact that JWT gives developers too much flexibility to choose the algorithm is like giving them a gun to shoot themselves in the foot.
Trivial Forgery
But it’s not the worst. JSON web token makes token forgery so trivial, that if you are not careful in your implementation or if you choose a poorly implemented library for your project, your system will easily become a vulnerable target.
One bad thing about JWT is that it includes the signing algorithm in the token header.
Because of this, we have seen in the past, an attacker can just set the alg
header to none
to bypass the signature verification process.
Of course, this issue has been identified and fixed in many libraries, but it’s something you should carefully check when choosing the community-developed library for your project.
Another more dangerous potential attack is to purposely set the algorithm header to a symmetric-key one, such as HS256
while knowing that the server actually uses an asymmetric-key algorithm, such as RSA
to sign and verify the token.
Let me explain how!
Basically, the server’s RSA public key is clearly known to the public because it’s a public key.
So the hacker can just create a fake token of the admin user, where he purposely set the algorithm header to HS256
, which is a symmetric-key algorithm.
Then, he just signs this token with the server’s public key and uses it to access resources on the server.
Now, keep in mind that, the server normally uses an RSA
algorithm, such as RS256
to sign & verify the token, so it will use the RSA
public key as the key to verify the token signature.
However, since the token’s algorithm header is saying HS256
, the server will verify the signature with this symmetric algorithm HS256
instead of RSA
.
And because the same key is used by the hacker to sign the token payload, this signature verification process will be successful, and the request of the hacker will be authorized.
This kind of attack is very simple, but still so powerful and dangerous, and it has actually happened in the past because the developers didn’t check the algorithm header before verify the token signature.
So, in order to prevent this attack, it’s crucial that in your server code, you must check the token’s algorithm header to make sure that it matches with the one your server uses to sign and verify tokens.
OK, so now you know why JSON web token is not a very well-designed standard. It opens the door to many potential threats.
Therefore, many people are trying to stay away from it, and migrate to something more robust.
PASETO - Platform Agnostic Security Token
PASETO, or Platform Agnostic Security Token is one of the most successful designs that is being widely accepted by the community as the best-secured alternative to JWT.
Strong algorithms
It solves all issues of JSON web token by first, provide strong signing algorithms out of the box.
Developers don’t have to choose the algorithm anymore. Instead, they only need to select the version of PASETO
they want to use.
Each PASETO
version has already been implemented with 1 strong cipher suite. And at any time, there will be only at most 2 latest versions of PASETO
are active.
Right now, 2 active PASETO
versions are version 1 and version 2.
PASETO version 1
Version 1 is older, and should only be used for legacy systems that cannot use modern cryptography.
Similar to JWT
, PASETO
also has 2 algorithm categories for 2 main use cases.
For local or internal services, we use a symmetric-key algorithm.
But unlike JWT, which only does base64-encode the payload, and sign the token, PASETO
actually encrypts and authenticates all data in the token with a secret key, using a strong Authenticated Encryption with Associated Data (or AEAD
) algorithm. If you don’t know what AEAD is, you can watch my video about SSL/TLS.
The AEAD
algorithm used in PASETO
version 1 is AES256 CTR
with HMAC SHA384
.
For public cases, where there are external services that need to verify the token, we have to use an asymmetric-key algorithm.
In that case, PASETO
uses the same approach as JWT
, which means, it doesn’t encrypt the token data, but only base64-encode it, and uses the private key to sign the content with a digital signature.
The chosen asymmetric-key algorithm in PASETO
version 1 is RSA PSS
with SHA384
.
PASETO version 2
In the latest version of PASETO
(version 2), 2 more secured and modern algorithms are being used.
For local symmetric-key scenario, it uses XChacha20
with Poly1305
algorithm.
And for a public asymmetric-key scenario, Edward-curve digital signature algorithm with curve 25519
is used.
This choice reminds me of how TLS 1.3
was designed to improve the security of its older version TLS 1.2
, and also simplify & reduce the number of TLS cipher suites at the same time.
Non-trivial forgery
Now with the design of PASETO, token forgery is no longer trivial.
Because the algorithm header doesn’t exist anymore, so the attacker cannot set it to none
, or force the server to use the algorithm it chose in this header.
Everything in the token is also authenticated with AEAD
, so it’s not possible to tamper with it.
Moreover, if you use a local symmetric-key algorithm, the payload is now encrypted, not just encoded, so it’s impossible for hackers to read or change the data stored in the token without knowing the server’s secret key.
Sounds amazing, right?
In the next lecture, I’m gonna show you how to implement both JWT
and PASETO
using Golang.
You will see PASETO
not only makes it safer but also easier and so much simpler to implement, compared to JWT
.
For now, let’s take a look at the structure of a PASETO
token.
This is a PASETO
version 2 token for local usage purposes. There are 4 main parts of the token, separated by a dot.
The first part is PASETO
version (with red color), which is version 2
.
The second part is the purpose of the token, is it used for local
or public
scenarios? In this case, it is local
, which means using a symmetric-key authenticated encryption algorithm.
The third part (with green color) is the main content or the payload data of the token. Note that it is encrypted, so if we decrypt it using the secret key, we will get 3 smaller parts:
- First, the payload body. In this case, we just store a simple message and the expiration time of the token.
- Second, the nonce value that is used in both encryption and message authentication process.
- And finally the message authentication tag to authenticate the encrypted message and its associated unencrypted data.
In this case, the unencrypted data is the version, the purpose, and the footer of the token (with purple color).
You can store any public information in the footer because it won’t be encrypted like the payload body, but only base64
encoded. So anyone who has the token can decode it to read the footer data.
In this case, it is Paragon Initiative Enterprises, the one who invented PASETO
.
Note that the footer is optional, so you can have a PASETO token without a footer. For example, this is another PASETO token for the public usage scenario:
It only has 3 parts, with no footer. The first part is PASETO
version, which is version 2
.
The second part is its purpose: public
in this case, which means an asymmetric-key digital signature algorithm is used to sign the token, and its payload data will not be encrypted, but only base64
encoded.
As you can see here, the green part of the payload is actually the encoded body, which we can easily decode to get this JSON object.
While the blue part of the payload is the signature of the token, created by the digital signature algorithm using the private key.
The server will use its paired public key to verify the authenticity of this signature.
And that’s it for today’s lecture about token-based authentication.
We have learned about the design flaws of JSON Web Token
that causes many security issues in the past, and how PASETO
was invented to fix all of those problems, and thus, make our developers’ life much easier.
I hope you like this article, and see you in the next one, where we will write codes to create and verify JWT
and PASETO
tokens in Golang.
If you like the article, please subscribe to our Youtube channel and follow us on Twitter or Facebook for more tutorials in the future.
If you want to join me on my current amazing team at Voodoo, check out our job openings here. Remote or onsite in Paris/Amsterdam/London/Berlin/Barcelona with visa sponsorship.
Top comments (8)
As a developer, I don't see the advantages of PASETO over JWT. The weakness of header algorithm can be simply solved. JWT allows user to choose their encoding algorithm, which I consider more flexible. You're a developer, you have to know what are you doing, not completely relying on some third parties
Anyway, this article is a good explanation and comparison between JWT and PASETO. There're hundred articles out there just say "PASETO is better than JWT" without giving any evidence
cool
I've learned a lot from this post. Thank you!
Thanks for your explain. I've learned a lot!
ive learnt alot thanks
Very nicely explained.
will 22 to 58 lectures be released?