5 brothers that front-end authentication must know: cookie, session, token, jwt, single sign-on

Dachang Technology Advanced Front-end Node Advanced

Click on the top programmer's growth guide, pay attention to the public number

Reply 1, join the advanced Node exchange group

In this article you will find:

  • HTTP-based front-end authentication background

  • Why is a cookie the most convenient storage solution, and what are the ways to operate a cookie?

  • How is the session scheme implemented and what are the problems

  • How is the token scheme implemented, how is it encoded and tamper-proof? what does jwt do? Implementation and meaning of refresh token

  • What are the similarities and differences between session and token and their advantages and disadvantages

  • What is single sign-on? Implementation ideas and processing in the browser


from the state

"HTTP stateless" We know that HTTP is stateless. That is to say, the state between the HTTP requester and the responder cannot be maintained, it is all one-time, and it does not know what happened to the previous request. But in some scenarios, we need to maintain state. Most typically, when a user logs in to Weibo, posting, following, and commenting should be in the logged-in user state. What is the solution to "marking"? ::mark::.

In a school or company, your identity and account information will be entered from the day you enter the school, and then a card will be issued to you. In the future, you will only need to swipe this card for access control, punch-in, and consumption in the park.

"Front-end storage" This involves one-time, one-storage, one-area, easy-to-manage, and the login interface is directly returned to the front-end, and the front-end needs to find a way for storage.

The premise is that you have to carry the card with you.

There are many ways to store the front end.

  • The most arrogant is to hang it on the global variable, but this is an "experience card", and it will be gone once you refresh the page

  • The high-end ones are stored in cookies, localStorage, etc. This is a "membership card". No matter how you refresh it, as long as the browser is not cleared or expired, it will always hold this state.

Front-end storage is not expanded here. There is a place to save it, and when you request it, you can spell it into the parameters and bring it to the interface.

Cornerstone: cookies

But the front end is so troublesome, you have to save it yourself, and you have to find a way to take it out. Is there anything you don’t need to worry about?

Yes, cookies. A cookie is also a type of front-end storage, but compared to other methods such as localStorage, with the help of HTTP headers and browser capabilities, cookies can be rendered imperceptible to the front-end. The general process is this:

  • In the interface that provides the markup, through the Set-Cookie field of the HTTP return header, it is directly "seed" to the browser

  • When the browser initiates a request, it will automatically bring the cookie to the interface through the Cookie field of the HTTP request header.

"Configuration: Domain / Path"

You cannot enter Peking University with a Tsinghua campus card.

Cookie is to limit :: "space scope"::, through Domain (domain) / Path (path) two levels.

The Domain attribute specifies which domain names should be attached to this cookie when the browser sends an HTTP request. If this attribute is not specified, the browser will set it as the first-level domain name of the current URL by default. For example, www.example.com will be set to example.com, and if you visit any subdomain of example.com in the future, the HTTP request will also be Take this cookie with you. If the domain name specified by the server in the Set-Cookie field does not belong to the current domain name, the browser will reject the cookie. The Path attribute specifies which paths to attach this cookie to when the browser sends an HTTP request. As long as the browser finds that the Path attribute is the first part of the HTTP request path, it will bring this cookie in the header information. For example, if the PATH attribute is /, then the request /docs path will also include the cookie. Of course, the premise is that the domain name must be consistent. — Cookies — JavaScript Standard Reference Tutorial (alpha)

"Configuration: Expires / Max-Age"

After you graduate, the card will not work.

A cookie can also limit ::"time range":: through one of Expires, Max-Age.

The Expires attribute specifies a specific expiration time. After the specified time, the browser will no longer retain the cookie. Its value is in UTC format. If this property is not set, or set to null, the cookie is only valid in the current session. Once the browser window is closed and the current session ends, the cookie will be deleted. In addition, the browser determines whether the cookie expires according to the local time. Since the local time is imprecise, there is no way to guarantee that the cookie will expire at the time specified by the server. The Max-Age attribute specifies the number of seconds the cookie will exist from now on, such as 60 * 60 * 24 * 365 (ie, one year). After this time, the browser will no longer retain this cookie. If Expires and Max-Age are specified at the same time, the value of Max-Age will take precedence. If the Set-Cookie field does not specify the Expires or Max-Age attribute, then this cookie is a Session Cookie, that is, it only exists in this session. Once the user closes the browser, the browser will no longer retain this cookie. — Cookies — JavaScript Standard Reference Tutorial (alpha)

"Configuration: Secure / HttpOnly"

Some schools stipulate that no card holder is allowed to be swiped (what a wonderful school, hypothetical); some schools do not allow themselves to put stickers on the card.

A cookie can restrict ::"usage"::.

The Secure attribute specifies that the browser can only send this cookie to the server under the encrypted protocol HTTPS. On the other hand, if the current protocol is HTTP, the browser will automatically ignore the Secure attribute sent by the server. This property is just a switch, no value needs to be specified. If the communication is HTTPS protocol, this switch is automatically turned on. The HttpOnly attribute specifies that the cookie cannot be obtained through JavaScript scripts, mainly because the Document.cookie attribute, XMLHttpRequest object and Request API cannot obtain this attribute. In this way, the cookie is prevented from being read by the script, and the cookie is only carried when the browser sends an HTTP request. — Cookies — JavaScript Standard Reference Tutorial (alpha)

"HTTP headers read and write cookies" Looking back, how does HTTP write and pass cookies and their configuration? A Set-Cookie header returned by HTTP is used to write "one (and only one)" cookie to the browser, in the format of cookie key + configuration key. E.g:

Set-Cookie: username=jimu; domain=jimu.com; path=/blog; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

So what if I want to set several cookies at a time? Give several Set-Cookie headers (repeat is allowed in one HTTP request)

Set-Cookie: username=jimu; domain=jimu.com
Set-Cookie: height=180; domain=me.jimu.com
Set-Cookie: weight=80; domain=me.jimu.com

The Cookie header of the HTTP request is used by the browser to send all cookies that conform to the current "space, time, usage" configuration to the server. Because the screening judgment is made by the browser, there is no need to return the configuration content, as long as the key value is sent.

Cookie: username=jimu; height=180; weight=80

"Front-end reading and writing of cookies" The front-end can create cookies by itself. If the cookie created by the server is not added HttpOnly, congratulations, you can also modify the cookie he gave. Calls document.cookiecan create and modify cookies, and like HTTP, document.cookieonly one cookie can be manipulated at a time.

document.cookie = 'username=jimu; domain=jimu.com; path=/blog; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly';

The call document.cookiecan also read cookies, and like HTTP, can read all non- HttpOnlycookies.

console.log(document.cookie);
// username=jimu; height=180; weight=80

(Just a cookie attribute, why are the read and write behaviors different? Get / set to understand) "Cookies are the cornerstone of maintaining HTTP request status" After understanding cookies, we know that cookies are the most convenient way to maintain HTTP request status. Most Front-end authentication problems are solved by cookies. Of course, other storage methods can also be used (more or less mentioned later). So with storage tools, what's next?

Application scheme: server session

Thinking back now, what happened when you swiped your card?

In fact, there is only one id (probably your student number) stored on your card. When you swipe, the property system checks your information and account, and then decides "Can you enter this door?" "Which account should this chicken leg go to to deduct money? ".

This kind of operation, in the front-end and back-end authentication system, is called session. Typical session login/authentication process:

c43d3dd68492604e086a9123a53f51fe.png
  • Browser login sends the account password, the server checks the user database, and verifies the user

  • The server saves the user's login status as a Session and generates a sessionId

  • Return through the login interface and set the sessionId to the cookie

  • After that, the browser requests the business interface again, and the sessionId is brought along with the cookie

  • The server checks the sessionId to verify the session

  • After success, do business processing normally and return the result

"Session storage method" Obviously, the server only gives the cookie a sessionId, and the specific content of the session (which may include user information, session status, etc.) must be stored by itself. There are several ways to store:

  • Redis (recommended): In-memory database, redis Chinese official website. It is stored in the form of key-value, which is exactly the scene of sessionId-sessionData; and the access is fast.

  • Memory: directly into the variable. Once the service is restarted it's gone

  • Database: Normal database. Performance is not high.

"Session expiration and destruction" is very simple, as long as the stored session data is destroyed. The "distributed problem of Session" is usually a cluster on the server side, and the user request will go through a load balancing, not necessarily which machine is hit. Then once the machine requested by the user's subsequent interface is inconsistent with the machine he requested for login, or the machine requested for login is down, won't the session be invalid? There are now several solutions to this problem.

  • First, from the perspective of "storage", the session is centrally stored. If we use a separate Redis or ordinary database, we can store all sessions in a library.

  • The second is from the perspective of "distribution", so that requests from the same IP are all hit on the same machine during load balancing. Take nginx as an example, you can configure ip_hash to achieve this.

However, the first method is usually used, because the second method is equivalent to castrating the load balancing, and still does not solve the problem of "the machine requested by the user is down". The previous diagram of "session processing under node.js" is very clear, the server needs to realize the access to cookies and sessions, and there are still a lot of things to do. In npm, there are already encapsulated middleware, such as express-session-npm, the usage will not be posted. Here's the cookie it's kind of:

32122a652421ebedb58690c67ce356b4.png

express-session - npm mainly implements:

  • It encapsulates the read and write operations of cookies, and provides configuration fields, encryption methods, expiration times, etc.

  • It encapsulates the access operation of the session, and provides configuration items to configure the session storage method (memory/redis), storage rules, etc.

  • Provides the session attribute to req, controls the set/get of attributes and responds to cookie and session access, and provides some methods to req.session.


Application scheme: token

The maintenance of the session has caused a lot of trouble to the server. We have to find a place to store it, and we have to consider the problem of distribution, and even enable a set of Redis cluster for it alone. Is there a better way?

I thought of school again. Before the campus card technology, we all relied on the "student ID card". The doorman directly checked the faces on the student ID and me to confirm the validity period of the student ID, grade and other information, and then he was allowed to pass.

Looking back and thinking about it, a login scenario does not have to store too much in the session, so why not pack it directly into a cookie? In this way, the server does not need to store it. It only needs to verify the validity of the "certificate" carried by the cookie every time, and it can also carry some lightweight information. This method is usually called a token.

5b3cbad22a53b5a9e752a760d83f5f76.png

The token flow is as follows:

  • The user logs in, the server verifies the account password, and obtains the user information

  • Encode user information and token configuration into tokens, and send them to the browser through cookie set

  • After that, the user requests the business interface and carries the token through the cookie

  • The interface verifies the validity of the token and performs normal business interface processing

"The way the client token is stored" As mentioned in the previous cookie, the cookie is not the only way for the client to store the credentials. Because of its "statelessness", the validity period and usage restrictions of the token are included in the token content, and there is less dependence on the cookie management ability, and the client is more free to store it. But the mainstream way of web application is still put in cookie, after all, worry less. "Token expiration" So how do we control the validity period of the token? It's very simple, just put the "expiration time" in with the data, and judge it when verifying.

the encoding of the token

The way of coding is thrifty by people. "base64" such as cookie-session on the node side - npm library

Don't worry about the name, it is actually a token library, but it maintains a highly consistent usage with express-session-npm, and hangs the data to be stored on the session

Under the default configuration, when I give him a userid, he will be saved like this:

e2ca15a2ba2f15d3cab90b4b04ae6c43.png

Here eyJ1c2VyaWQiOiJhIn0=, it is {"userid":"abb”}the base64 of . "Tamper proof"

The question is, if the user cdd takes {"userid":"abb”}a base64, and then manually modifies his own token eyJ1c2VyaWQiOiJhIn0=, can he directly access the data of abb?

yes. So depending on the situation, if the token involves sensitive permissions, we must find a way to prevent the token from being tampered with. The solution is to sign the token to identify whether the token has been tampered with. For example, in the cookie-session-npm library, add two configurations:

secret: 'iAmSecret',signed: true,

In this way, there will be a variety of .sig cookie, the value inside is {"userid":"abb”}and iAmSecretcalculated by encryption algorithm, such as HMACSHA256 class (System.Security.Cryptography) | Microsoft Docs.

915c70d9e15c99bd7c62575f05d035cf.png

Well, now although cdd can forge eyJ1c2VyaWQiOiJhIn0=, but cannot forge the content of sig, because he doesn't know secret. "JWT" ​​But the above approach increases the number of cookies, and the data itself does not have a standardized format, so JSON Web Token Introduction - jwt.io was born.

JSON Web Token (JWT) is an open standard that defines a way to communicate JSON information. This information is digitally signed to ensure trustworthiness.

It is a mature token string generation scheme that contains the data and signatures we mentioned earlier. Let's take a look at what a JWT token looks like:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJhIiwiaWF0IjoxNTUxOTUxOTk4fQ.2jf3kl_uKWRkwjOP6uQRJFqMlwSABcgqqcJofFH5XCo

How did this string of things come about? Look at the picture:

3c54e122f31ae12395c9b930f66d41a9.png

Type, encryption algorithm options, and JWT standard data fields, you can refer to RFC 7519 - JSON Web Token (JWT) node There are also related library implementations: express-jwt - npm koa-jwt - npm

refresh token

Token, as a permission guardian, the most important thing is "security". The token used by the business interface for authentication, we call it an access token. The more permission-sensitive the business, the more we want the access token to have a short validity period to avoid being stolen. However, if the validity period is too short, the access token will often expire. What should I do after it expires? One way is to let the user log in again to obtain a new token, which is obviously not friendly enough. It is necessary to know that some access tokens may only expire a few minutes. Another way is to add another token, a token specially generated for access token, which we call refresh token.

  • The access token is used to access the business interface. Since the validity period is short enough, the risk of misappropriation is small, and the request method can also be made looser and more flexible.

  • The refresh token is used to obtain the access token, the validity period can be longer, and the security is increased through independent services and strict request methods; due to infrequent verification, it can also be processed as the previous session.

With the refresh token, the request process in several cases becomes like this:

0dfa19e830f15389262ff9d6f1324668.png

If the refresh token also expires, you can only log in again.

session and token

Session and token are concepts with very vague boundaries. As mentioned above, refresh token may also be organized and maintained in the form of session. In a narrow sense, we usually think that session is an authentication scheme that is "planted on a cookie and the data is stored on the server", and a token is an authentication scheme that "can be stored anywhere on the client side, and data is stored in the token". The comparison between session and token is essentially a comparison of "the client stores cookies/stores elsewhere" and "the server stores data/does not store data". "Storing cookies on the client side / saving them elsewhere" is convenient and not to worry about, but the problem is also obvious:

  • On the browser side, cookies can be used (in fact, tokens are commonly used cookies), but what if there is no cookie on the browser side?

  • Cookies are automatically carried by browsers under the domain, which is prone to CSRF attacks (Front-end Security Series (2): How to Prevent CSRF Attacks? - Meituan Technical Team)

If you save it elsewhere, you can solve the scenario without cookies; manually bring it through parameters, etc., you can avoid CSRF attacks. "Data stored on server / No data stored"

  • Data storage: The request only needs to carry the id, which can greatly shorten the length of the authentication string and reduce the size of the request

  • No data storage: does not require a complete set of solutions and distributed processing on the server side, reducing hardware costs; avoiding verification delays caused by database checking


sign in

As we have already seen earlier, in the client/server authentication system under the same domain, the client carries the credentials to maintain the login state for a period of time. But when we have more and more business lines, there will be more business systems scattered under different domain names, and we need the ability of "one login, universal access", which is called "single sign-on".

"Fake" single sign-on (same primary domain name)

Simple, if the business systems are all under the same main domain name, for example wenku.baidu.com tieba.baidu.com, it is easy to handle. You can directly set the cookie domain as the main domain name baidu.com, which is what Baidu does.

d3a5c6e7e7cf86725e9118dd8150aef2.png

"Real" single sign-on (different primary domain name)

For example, a trendy company like Didi also owns an didichuxing.com xiaojukeji.com didiglobal.comequal domain name, so the use of cookies is completely unavoidable. This is the real single sign-on if it can achieve "one login, universal access across the board". In this scenario, we need an independent authentication service, usually called SSO. "A complete process of "initiating login from system A, without logging in to system B""

cb48eac6e2d8e62c3efba919de3b2ca1.png
  • The user enters the A system without the login credentials (ticket), and the A system jumps to the SSO for him

  • If you have not logged in with SSO, there is no certificate under the sso system (note that this is different from the previous A ticket), enter the account password to log in

  • If the SSO account password verification is successful, the interface returns to do two things: one is to plant the credentials under the sso system (record the user's login status in SSO); the other is to issue a ticket

  • The client gets the ticket, saves it, and requests the system A interface

  • System A verifies the ticket and processes the service request normally after success

  • At this time, the user enters the system B for the first time and has no login credentials (ticket), and the B system jumps to the SSO for him.

  • You have logged in through SSO, and there are credentials in the system. You don’t need to log in again, you only need to issue a ticket

  • The client gets the ticket, saves it, and requests the system B interface

The above process of "Full Version: Consider the Browser Scenario" seems to be no problem. In fact, this is enough for many APPs and other terminals. But it doesn't work very well in the browser. look here:

ae97eb439c5c14ddd040c515502a6485.png

For the browser, how should the data returned in the SSO domain be stored so that it can be brought when visiting A? Browsers have strict restrictions on cross-domain, cookies, localStorage and other methods have domain restrictions. This requires and can only be provided by A to provide the ability to store credentials under the A domain. Usually we do this:

c7ffed81fb713f5385d5e5f8698a58d3.png

In the figure, we mark the domain name where the browser is currently located by color. Note the change in the description part of the text on the gray background in the figure.

  • In the SSO domain, SSO does not directly return the ticket through the interface, but redirects it to the interface of system A through a URL with a code. This interface is usually agreed when A registers with SSO

  • The browser is redirected to the A domain, and accesses the callback interface of A with the code, and the callback interface exchanges the ticket with the code

  • This code is different from the ticket, the code is one-time, exposed in the URL, just to pass a ticket to change, it will be invalid after the change

  • After the callback interface gets the ticket, set the cookie in its own domain successfully

  • In subsequent requests, you only need to parse the ticket in the cookie and go to SSO for verification.

  • The same goes for accessing the B system


Summarize

  • HTTP is stateless, in order to maintain front and back requests, front-end storage tags are required

  • Cookie is a perfect way of marking. It is operated through HTTP header or js and has corresponding security policies. It is the cornerstone of most state management schemes.

  • Session is a state management scheme. The front end stores id through cookies, and the back end stores data, but the back end has to deal with distributed problems

  • Token is another state management solution. Compared with session, it does not require back-end storage. All data is stored in the front-end, liberating the back-end and releasing flexibility.

  • The encoding technology of token, usually based on base64, or adding encryption algorithm to prevent tampering, jwt is a mature encoding scheme

  • In complex systems, tokens can be decentralised through service token and refresh token, while satisfying security and user experience

  • The comparison between session and token is the comparison between "whether to use cookies" and "whether it exists in the backend"

  • Single sign-on requires systems in different domains to "log in once, and use it across the board". Usually, an independent SSO system records the login status and issues tickets, and each business system cooperates to store and authenticate tickets

Reprinted from: Henrylulu

https://juejin.cn/post/6898630134530752520

Node 社群


我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。

如果你觉得这篇内容对你有帮助,我想请你帮我2个小忙:

1. 点个「在看」,让更多人也能看到这篇文章2. 订阅官方博客 www.inode.club 让我们一起成长

点赞和在看就是最大的支持❤️

Guess you like

Origin blog.csdn.net/xgangzai/article/details/124464030