Eight cartoons understand the single sign on system designed by JWT

Time:2021-7-29

JSON web token (JWT) is a very lightweight specification. This specification allows us to use JWT to transfer safe and reliable information between users and servers.

Let’s imagine a scene. When user a pays attention to user B, the system sends an email to user B with a link “click here to pay attention to user a”. The address of the link can be like this

https://your.awesome-app.com/make-friend/?from_user=B&target_user=A

The above URL mainly describes this through the URL. Of course, there is a disadvantage in doing so, that is, user B must log in first. Can you simplify this process so that B users can complete this operation without logging in. JWT allows us to do this.

Eight cartoons understand the single sign on system designed by JWT

Composition of JWT

A JWT is actually a string, which consists of three parts,headloadAndautograph

Load (payload)

We first describe the above operation of adding friends as a JSON object. Some other information is added to help the server receiving the JWT understand the JWT in the future.

{
    "iss": "John Wu JWT",
    "iat": 1441593502,
    "exp": 1441594722,
    "aud": "www.example.com",
    "sub": "[email protected]",
    "from_user": "B",
    "target_user": "A"
}

The first five fields are defined by the JWT standard.

  • ISS: issuer of the JWT
  • Sub: the user the JWT is targeting
  • Aud: the party receiving the JWT
  • Exp (expires): when does it expire? Here is a UNIX timestamp
  • IAT (issued at): when was it issued

These definitions can be found in the standard.

The following string can be obtained by [Base64 encoding] the above JSON object. This string we call JWTPayload(load).

eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdW

If you use node.js, you can use the package base64url of node.js to get this string.

Little knowledge: Base64 is a kind of code, that is, it can be translated back to its original appearance. It is not an encryption process.

var base64url = require('base64url')
var header = {
    "from_user": "B",
    "target_user": "A"
}
console.log(base64url(JSON.stringify(header)))
//Output: eyjpc3mioijkb2huifd1iepxvcisimlhdci6mtq0mtu5mzuwmiwiwizxhwijoxndqxntk0nziylcjhdwqioij3d3cuzxhhbxbszs5jb20ilcjzdwiijqcm9ja2v0qgv4yw1wbguuy29tiwiznjvbv91c2vyijoiqiiinrhcmdf91c2vyijoiqsiq9

Header

JWT also needs a header, which is used to describe the most basic information about the JWT, such as its type and the algorithm used for signature. This can also be represented as a JSON object.

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

Here, we show that this is a JWT, and the signature algorithm we use (which will be mentioned later) is hs256 algorithm.

It also needs to be Base64 encoded, and the subsequent string becomes the name of JWTHeader(head).

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

Signature (signature)

Connect the above two encoded strings with periods (the head is in the front) to form

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0

This part of the process is reflected in the source code of node JWs

Finally, we encrypt the spliced string with hs256 algorithm. When encrypting, we also need to provide a secret. If we use mystar as the key, we can get the encrypted content

rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

This part is also calledautograph

Eight cartoons understand the single sign on system designed by JWT

Finally, this part of the signature is spliced behind the signed string, and we get the complete JWT

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn

So we can change the URL in the email to

https://your.awesome-app.com/make-friend/?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJm

In this way, you can safely complete the operation of adding friends!

Wait a minute, we must have some problems:

  1. What is the purpose of signing?
  2. Base64 is a kind of coding and reversible, so my information will not be exposed?

Let me explain for you one by one.

Purpose of signature

The last step of the signature process is actually to sign the header and payload content. Generally speaking, the output of encryption algorithm is always different for different inputs. For two different inputs, the probability of producing the same output is extremely small (possibly smaller than my probability of becoming the richest man in the world). Therefore, let’s treat “different inputs produce different outputs” as an inevitable event.

Therefore, if someone decodes and modifies the contents of the header and payload before encoding, the signature of the new header and payload will be different from the previous signature. Moreover, if you do not know the key used by the server for encryption, the resulting signature will be different.

Eight cartoons understand the single sign on system designed by JWT

After receiving the JWT, the server application will first re sign the contents of the header and payload with the same algorithm. So how does the server application know which algorithm we use? Don’t forget that we have indicated our encryption algorithm with the alg field in the JWT header.

If the server application signs the header and payload in the same way again and finds that the signature calculated by itself is different from the received signature, it means that the content of the token has been moved by others. We should reject the token and return an HTTP 401 unauthorized response.

Information will be exposed?

yes.

Therefore, in JWT, no sensitive data should be added to the load. In the above example, we transfer the user ID of the user. This value is actually not sensitive and is generally known to be safe.

But content like passwords cannot be placed in JWT. If you put the user’s password in JWT, a malicious third party can quickly know your password through Base64 decoding.

Applicable scenarios of JWT

We can see that JWT is suitable for delivering some non sensitive information to web applications. For example, the above-mentioned operation of adding friends, as well as the operation of the following orders, etc.

Eight steps for user authentication

The so-called user authentication is a mechanism that allows users to log in and allow users to use their account when accessing the website in the next period of time without logging in again.

Tip: don’t confuse user authentication with user authorization. User authorization refers to specifying and allowing users to use their own permissions, such as posting, managing sites, etc.

First, the server application (hereinafter referred to as “application”) allows users to send their user name and password to the server interface through a web form. This process is generally an HTTP post request. The recommended way is to use SSL encrypted transmission (HTTPS protocol), so as to avoid sensitive information being sniffed.

Eight cartoons understand the single sign on system designed by JWT

Next, the application checks the user name and password with the database.

Eight cartoons understand the single sign on system designed by JWT

After checking the user name and password successfully, the application will the user’s ID (user in the figure_ ID) as an attribute of JWT payload, it is combined with the header by Base64 coding to form a JWT. JWT here is a string of the same form as lll.zzz.xxx.

Eight cartoons understand the single sign on system designed by JWT

The application returns the JWT string to the user as part of the request cookie. Note that the httponly attribute must be used here to prevent cookies from being read by JavaScript, so as to avoid cross site scripting attacks (XSS attacks).

Eight cartoons understand the single sign on system designed by JWT

Before the cookie expires or is deleted, the application will receive the cookie containing JWT every time the user visits the application. Thus, the application can extract the JWT from the request.

Eight cartoons understand the single sign on system designed by JWT

The application checks the effectiveness of JWT through a series of tasks. For example, check whether the signature is correct; Check whether the token has expired; Check whether the receiver of the token is itself (optional).

Eight cartoons understand the single sign on system designed by JWT

After the application confirms that the JWT is valid, the JWT performs Base64 decoding (which may have been completed in the previous step), and then reads the user’s ID value in the payload, that is, user_ ID attribute. Here, the user ID is 1025.

Eight cartoons understand the single sign on system designed by JWT

The application obtains the information of the user with ID 1025 from the database, loads it into memory, and initializes a series of underlying logic such as orm.

Eight cartoons understand the single sign on system designed by JWT

The application responds to the user’s request.

Eight cartoons understand the single sign on system designed by JWT

Difference between session and session storage ID

The biggest disadvantage of storing user ID in session mode is that it takes up a lot of server memory, and it may save a lot of state for larger applications. Generally speaking, large applications also need to use some kV databases and a series of caching mechanisms to store sessions.

JWT mode disperses the user state to the client, which can significantly reduce the memory pressure on the server. In addition to the user ID, other user related information can also be stored, such as whether the user is an administrator and the bucket where the user is located (see [A / B test basics you should know](
/2015 / 08 / 27 / introduction to ab testing /).

Although JWT makes the server have some computing pressure (such as encryption, encoding and decoding), these pressures may be half as much as disk I / O. Whether it is adopted or not needs to speak with data in different scenarios.

Single sign on

The session mode is used to store the user ID. at first, the user’s session will only be stored on one server. For sites with multiple subdomains, each subdomain will correspond to at least one different server, for example:

  • www.taobao.com
  • nv.taobao.com
  • nz.taobao.com
  • login.taobao.com

Therefore, if you want to log in to login.taobao.com, you can still get sessions under other sub domain names, which requires us to synchronize sessions on multiple servers.

Using JWT does not have this problem, because the user’s state has been transmitted to the client. Therefore, we only need to set the domain containing the JWT cookie as the top-level domain name, for example

Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000; domain=.taobao.com

Note that the domain must be set to a dot plus top-level domain name, that is. Taobao.com. In this way, taobao.com and *. Taobao.com can accept the cookie and obtain the JWT.

Original text:https://u.nu/2k4wk
This article starts with the official account: Java web project. Welcome to pay attention to get more exciting content.