10

I tried to use eight cartoons to first let everyone understand how to design a normal user authentication system, and then extend it to the single sign-on system.

Introduction to JWT

JSON Web Token (JWT) is a very lightweight specification. This specification allows us to use JWT to transfer safe and reliable information between the user and the server.

Let us imagine a scenario. When user A follows user B, the system sends an email to user B with a link "click here to follow user A". The link address can be like this

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

The above URL mainly uses URL to describe this. Of course, there is a drawback of doing so, that is, user B must be logged in first. Can you simplify this process so that user B can complete this operation without logging in. JWT allows us to do this.

图片

Composition of JWT

A JWT is actually a string, which consists of three parts: header, payload and signature.

Payload

Let's first describe the operation of adding friends above as a JSON object. Some other information is added to help the server that receives this JWT in the future understand this JWT.

{
    "iss": "John Wu JWT",
    "iat": 1441593502,
    "exp": 1441594722,
    "aud": "www.example.com",
    "sub": "jrocket@example.com",
    "from_user": "B",
    "target_user": "A"
}

The first five fields are defined by the JWT standard.

  • iss: the issuer of the JWT
  • sub: the user the JWT is for
  • aud: The party who received the JWT
  • exp(expires): When does it expire, here is a Unix timestamp
  • iat(issued at): when was it issued

These definitions can all be found in the standard.

[base64 encoding] on the above JSON object can get the following string. We call this string the Payload of JWT.

eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9

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

var base64url = require('base64url')
var header = {
    "from_user": "B",
    "target_user": "A"
}
console.log(base64url(JSON.stringify(header)))
// 输出:eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9
Header

The 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 the signature. This can also be represented as a JSON object.

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

Here, we explained that this is a JWT, and the signature algorithm we use (mentioned later) is the HS256 algorithm.

It also needs to be Base64 encoded, and the string after that becomes the Header of the JWT.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
Signature (signature)

Connect the above two encoded strings with periods. (head first) to form

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0

This part of the process is reflected in the source code of node-jws

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

rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

This part is also called the signature.

图片

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

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM

So, we can change the URL in the email to

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

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

Eight Steps to User Authentication

The so-called user authentication (Authentication) is a mechanism that allows users to log in, and allows users to use their accounts when they visit the website for a period of time without the need to log in again.

Tips: Don't confuse user authentication with user authorization (Authorization). User authorization refers to stipulating and allowing users to use their own rights, such as publishing posts, managing sites, etc.

First, the server application (hereinafter referred to as "application") allows users to send their username 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) to prevent sensitive information from being sniffed.

图片

Next, the application and the database check the user name and password.

图片

After the user name and password are successfully checked, the application uses the user's id (user\_id in the figure) as an attribute of the JWT Payload, and base64-encodes it and the header to form a JWT. The JWT here is a string similar to lll.zzz.xxx.

图片

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

图片

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

图片

The application checks the validity of the JWT through a series of tasks. For example, check whether the signature is correct; check whether the Token has expired; check whether the recipient of the Token is yourself (optional).

图片

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, which is the user\_id attribute. The user's id here is 1025.

图片

The application fetches the user's information with an id of 1025 from the database, loads it into the memory, and performs a series of low-level logic initializations such as ORM.

图片

The application responds to user requests.

图片

sign in

The session method is used to store the user id. At the beginning, the user's session will only be stored on one server. For sites with multiple subdomains, each subdomain corresponds to at least one different server, for example:

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

So if you want to realize that after logging in at login.taobao.com, you can still get the Session under other subdomains, which requires us to synchronize the Session on multiple servers.

Using JWT does not have this problem, because the user's status has been transmitted to the client. Therefore, we only need to set the domain containing the JWT cookie to 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, namely .taobao.com. In this way, both taobao.com and *.taobao.com can accept this cookie and get the JWT.

Author: Zihui (John Wu)
blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/


民工哥
26.4k 声望56.7k 粉丝

10多年IT职场老司机的经验分享,坚持自学一路从技术小白成长为互联网企业信息技术部门的负责人。2019/2020/2021年度 思否Top Writer