📜 ⬆️ ⬇️

Five easy steps for understanding JSON Web Tokens (JWT)

jwt


I present to you my rather loose translation of Article 5 Easy Steps to Understanding JSON Web Tokens (JWT) . This article will discuss what JSON Web Tokens (JWT) are and what they eat. That is, what role do they play in user authentication and ensuring the security of application data.


First, consider the formal definition.


JSON Web Token (JWT) is a JSON object that is defined in the open standard RFC 7519 . It is considered one of the safe ways to transfer information between two participants. To create it, it is necessary to define a header with general information on the token, payload data, such as user id, its role, etc. and signatures (signature).
By the way, JWT is correctly pronounced as /dʒɒt/

In simple terms, JWT is just a string in the following format header.payload.signature .
Suppose we want to register on the site. In our case, there are three parties — user user , application server and authentication server . The authentication server will provide the user with a token with which he can later interact with the application.


How the application uses JWT to verify user authentication.


The application uses JWT to verify user authentication as follows:


  1. First, the user enters the authentication server using an authentication key (it can be a login / password pair, or a Facebook key, or a Google key, or a key from another account).
  2. The authentication server then creates the JWT and sends it to the user.
  3. When a user makes a request to the application's API, he adds the previously received JWT to it.
  4. When a user makes an API request, the application can check on the JWT submitted with the request whether the user is who he claims to be. In this scheme, the application server is configured to check whether the incoming JWT is exactly what was created by the authentication server (the verification process will be explained later in more detail).

JWT structure


JWT consists of three parts: header header , payload and signature signature . Let's go through each of them.


Step 1. Create a HEADER


The JWT header contains information on how the JWT signature should be calculated. A header is also a JSON object that looks like this:


 header = { "alg": "HS256", "typ": "JWT"} 

The typ field does not tell us anything new, just that it is JSON Web Token . More interesting here is the alg field, which defines the hashing algorithm. It will be used when creating the signature. HS256 is nothing more than a HMAC-SHA256 ; only one secret key is needed to calculate it (for more details, see step 3). Another RS256 algorithm can also be used - unlike the previous one, it is asymmetric and creates two keys: public and private. Using a private key, a signature is created, and using a public key, only the authenticity of the signature is verified, so we do not need to worry about its security.


Step 2. Create PAYLOAD


Payload is payload that is stored inside JWT . This data is also called JWT-claims . In the example that we are considering, the authentication server creates a JWT with information about the user id - userId .


 payload = { "userId": "b08f86af-35da-48f2-8fab-cef3904660bd" } 

We put only one claim in the payload . You can put as many applications as you like. There is a list of standard applications for JWT payload - here are some of them:



These fields can be useful when creating JWT , but they are not required. If you want to know the entire list of available fields for JWT , you can have a look at the Wiki . But it is worth remembering that the more information is transmitted, the more JWT itself will end up as a result. Usually there are no problems with this, but still it can negatively affect performance and cause delays in the interaction with the server.


Step 3. Create SIGNATURE


The signature is computed using the following pseudo-code:


 const SECRET_KEY = 'cAtwa1kkEy' const unsignedToken = base64urlEncode(header) + '.' + base64urlEncode(payload) const signature = HMAC-SHA256(unsignedToken, SECRET_KEY) 

The base64url algorithm encodes the header and payload created in steps 1 and 2 . The algorithm connects the encoded strings through a dot. Then, the resulting string is hashed by the algorithm specified in the header based on our secret key.


 // header eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 // payloadey J1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ // signature -xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM 

Step 4. Now combine all three JWT components together.


Now that we have all three components, we can create our JWT . It's quite simple, we connect all the received elements into a string through a dot.


 const token = encodeBase64Url(header) + '.' + encodeBase64Url(payload) + '.' + encodeBase64Url(signature) // JWT Token // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM 

You can try creating your own JWT at jwt.io.
Let's return to our example. Now the authentication server can send to the user JWT .


How does JWT protect our data?


It is very important to understand that using JWT does NOT hide or mask data automatically. The reason why JWT is used is to verify that the data sent was actually sent to an authorized source. As demonstrated above, the data inside JWT is encoded and signed, note that this is not the same thing that is encrypted. The purpose of data coding is structure transformation. Signed data allows the recipient to verify the data source authentication. Thus, encoding and signing data does not protect them. On the other hand, the main purpose of encryption is to protect data from unauthorized access. For a more detailed explanation of the difference between encryption and encryption, as well as how hashing works, see this article . Since JWT is only encoded and signed, and since JWT is not encrypted, JWT does not guarantee any security for sensitive data.


Step 5. Verify JWT


In our simple example of 3 participants, we use JWT , which is signed using the HS256 algorithm, and only the authentication server and the application server know the secret key. The application server receives the secret key from the authentication server during the installation of authentication processes. Since the application knows the secret key when the user makes an API request with a token attached to it, the application can perform the same signing algorithm for JWT as in step 3 . The application can then verify this signature by comparing it with its own calculated hashing. If the signatures match, then JWT is valid, i.e. came from a trusted source. If the signatures do not match, then something went wrong - perhaps this is a sign of a potential attack. Thus, while testing JWT , the application adds a layer of trust between itself and the user.


Finally


We walked through what JWT is , how it is created and how it is validated, how it can be used to establish trust between the user and the application. But this is only a piece of the puzzle of a large topic of authorization and ensuring the protection of your application. We considered only the basics, but without them it is impossible to move on.


useful links


  1. 5 Easy Steps to Understanding JSON Web Tokens (JWT)
  2. Securing React Redux Apps With JWT Tokens
  3. Why do I need Refresh Token if there is Access Token?

')

Source: https://habr.com/ru/post/340146/


All Articles