OAuth2.0 practical summary


title: OAuth2.0 Practical Summary
date: 2023-01-30 11:23:12
tags:

  • OAuth2.0
    categories:
  • Development technology and framework
    cover: https://cover.png
    feature: false

insert image description here

1 Introduction

1.1 What is OAuth 2.0?

In one sentence, OAuth 2.0 is an authorization protocol. So how do you understand the "authorization" here?

Give an example from real life. Suppose you want to go to Baidu to visit your big client Mr. Wang. After arriving at Baidu's building, the security guard stops you and asks you for a badge. You said: "I'm here to visit Mr. Wang, and I don't have a badge." The security guard said: "Then you have to go to the front desk to register."

When you come to the front desk, the lady at the front desk asks if you have made an appointment. You said that General Secretary Wang asked for your mobile phone number yesterday, saying that he had already made an appointment. After confirmation, the lady sent a verification code to your mobile phone. After you told the verification code to the lady at the front desk, she gave you an access control card, so you can use the access control card to pass

There is one authorization in this example. Originally, you did not have permission to enter the Baidu building, but after a series of verifications by the lady at the front desk, she found that you were indeed here to visit a client, so she gave you a temporary work card. This whole process is authorization

Take another e-commerce scenario. Suppose you are a seller and you have opened a store on JD.com. In daily operations, you need to print out the order for delivery to users. But printing is also quite cumbersome. You used to do it manually before, but later you found out that there is a third-party software called "Little Rabbit", which can help you deal with this matter efficiently.

But how did Xiaotu access these order data? JD.com provides an open platform. Xiaotu can access the user's order data through the API of JD.com's open platform. As long as you click Agree in the software, Xiaotu can get an access token and obtain it through the access token. To your order data to help you work. There is also an authorization here. If you do not agree, the platform will not dare to give these data to third-party software.

1.2 Why use OAuth 2.0?

Based on the solutions for the above two scenarios, the easiest solution for authorization is to provide keys. For example, if you are going to Baidu to visit Mr. Wang, the lady at the front desk will give you a Baidu badge; if Xiaotu wants to get your order information, then you will give it your username and password. But with a little security awareness, none of us would do that

Because you have a Baidu badge, you can freely enter and exit at any time, which is obviously not what Baidu wants. Therefore, Baidu has a complete set of mechanisms. By giving you a temporary work card, it allows you to meet Mr. Wang in the building while ensuring safety. Correspondingly, the process of Xiaotu software requesting access to your order data will also involve such an authorization mechanism, which is OAuth 2.0. It works for you by giving Xiaotu software an access token instead of letting Xiaotu software hold your username and password to obtain your order data

In fact, apart from Xiaotu software, there are many places where OAuth 2.0 is used in today's Internet world, just because it hides the implementation details and requires more analysis to discover it. For example, when you use WeChat to log in to other websites or apps, when you start using a small program, you use OAuth 2.0 without knowing it

In summary, OAuth 2.0 is an authorization protocol that ensures that third parties (software) can further access the authorizer's data only after they are authorized . Therefore, it is often also true that OAuth 2.0 is a security protocol heard

Now access to the authorizer's data is mainly through Web API, so whenever this kind of external API is to be protected, such an authorization method is required. And OAuth 2.0's mechanism for issuing access tokens is a perfect method. At the same time, such Web APIs are still increasing, so OAuth 2.0 is currently one of the important security methods on the Web.

1.3 How does OAuth 2.0 work?

Taking the above-mentioned example of Xiaotu ordering software, assuming that Xiao Ming opened a store on JD.com, Xiao Ming wants to manage the orders in his store, so he chooses to use Xiaotu software. Software" and "Jingdong Merchant Open Platform" into a dialogue to see how "they" communicate

Xiao Ming: "Hello, Xiaotusoft. I am on Google browser and need to visit you to help me process my order in Jingdong Mall store"

Xiaotu Software: "Okay, I need you to authorize me. Now I will guide you to the Jingdong Merchant Open Platform, where you will authorize me"

Jingdong Merchant Open Platform: "Hello, Xiaoming. I received a request from Xiaotu software, and now I have prepared an authorization page. After you log in and confirm, click the authorization button on the authorization page."

Xiao Ming: "Okay, Jingdong merchants open the platform. I saw this authorization page and clicked the authorization button"

Jingdong Merchant Open Platform: "Hello, Xiaotu ordering software. I have received Xiao Ming's authorization, and now I want to generate an authorization code code value for you. I redirect you to your callback URL address through the browser."

Xiaotu Software: "Okay, Jingdong merchants open the platform. I got the authorization code from the browser now, and now I will use this authorization code to request you. Please give me an access token access_token."

Jingdong Merchant Open Platform: "Okay, Xiaotu order software, the access token has been sent to you"

Xiaotu ordering software: "Great, I can now use the access token to get orders from Xiaoming's store"

Xiao Ming: "I have been able to see my order, and now I will start the ordering operation"

insert image description here

Analyzing this process again, it is not difficult to find that the ultimate purpose of Xiaotu software is to obtain something called an "access token". It can also be seen from the last step that after Xiaotu software obtains the access token, it has enough "capability" to request orders from Xiaoming's store, that is, it can help Xiaoming print orders

So, how does Xiaotu software obtain the value of the access token? You will find that there is another thing called "authorization code", which means that Xiaotu software is an access token in exchange for the authorization code

How did Xiaotu software get the authorization code? From the first step of the process in the figure, you will find that the authorization code is generated after Xiao Ming authorizes it. All subsequent actions in the above process are actually generated after Xiao Ming authorizes Xiaotu software. The main action is to generate an authorization code –> generate an access token –> use an access token

At this point, it is not difficult to find that the core of OAuth 2.0 authorization is to issue and use access tokens , and no matter what type of authorization process it is, it is the core of the entire process

In the example of Xiaotu software, the type of authorization code license (Authorization Code) is used. It is the most classic, complete, safest, and most widely used permission type in OAuth 2.0. In addition to the authorization code permission type, OAuth 2.0 has three basic permission types for different usage scenarios, namely implicit permission (Implicit), client credentials permission (Client Credentials), resource owner credentials permission (Resource Owner Password Credentials). Relatively speaking, the processes of these three authorization types are weakened in terms of process complexity and security

2. Authorization code

Earlier, we mentioned the authorization code permission type of OAuth 2.0. In the example of Xiaotu’s ordering software, Xiaotu finally requests the order data in Xiaoming’s store through the access token. It is also mentioned that this access token is exchanged for an authorization code. Why use an authorization code in exchange for a token? Why can't access tokens be issued directly?

2.1 Why do I need an authorization code?

Before talking about this issue, we must first understand that there are four roles in the OAuth 2.0 system. According to the official name, they are resource owner, client, authorization service and protected resource. However, the client here, I prefer to call it a third-party software, and in the follow-up, it will be called a third-party software

Take Xiaotu software as an example, and the official title is "reflected into reality". The corresponding relationship is, resource owner -> Xiao Ming, third-party software -> Xiaotu software, authorization service -> JD Merchant Open Platform authorization service, Protected resource -> Xiao Ming's store orders on JD.com

At the beginning of OAuth's birth, it was to solve the authorization problem in the Web browser scenario. Therefore, based on the browser scenario, based on the overall process of Xiaoming using Xiaotu software to print orders in the previous lecture, an authorization code license is drawn. Types of sequence diagrams. In order to better describe the authorization code licensing process, the front-end and back-end of Xiaotu software are shown separately, and the system of JD Merchant Open Platform is divided into authorization service and protected resource service according to OAuth 2.0 components. As shown below:

insert image description here

As can be seen from the figure, the authorization service generates the authorization code code in step 4. According to the question raised at the beginning, if the authorization code is not required, this step can actually directly return the access token access_token

Continue to think about this without an authorization code, if the access token is returned directly here, then the redirection method must not be used. Because this will expose the access token with high security and confidentiality requirements on the browser, which will face the security risk of access token theft. Obviously, this cannot be allowed

In other words, if there is no authorization code, the access token can only be sent to the backend service of the third-party software Xiaotu. According to this logic, the above flow chart will become as follows:

insert image description here

So far, it looks flawless. Xiaoming visits Xiaotusoft, and Xiaotusoft says that you have to authorize me if you want to place an order, otherwise JD.com will not do it. Then Xiaotusoft guides Xiaoming to jump to JD.com’s authorization service. After the authorization service, JD Merchant Open Platform verified Xiaotu’s legitimacy and Xiaoming’s login status, and then generated an authorization page. Immediately afterwards, Xiao Ming quickly clicked to agree to the authorization. At this time, the Jingdong Merchant Open Platform knew that Xiao Ming’s order data could be given to Xiaotu Software

Therefore, JD Merchant opened the platform without ambiguity, and quickly generated an access token access_token, and returned it to Xiaotu software through the back-end service. At this time, Xiaotu software can work normally.

In this way, the problem arises. When Xiao Ming is redirected to the authorization service by the browser, the "connection" between Xiao Ming and Xiaotu software is broken, which is equivalent to the moment Xiao Ming establishes a "connection" with the authorization service , will always "stay on the page" of the authorization service. In the time sequence at the question mark in Figure 2, Xiao Ming never reconnected to the Xiaotu software

However, at this time, Xiaotu software has obtained the access token authorized by Xiaoming, and also used the access token to obtain the order data in Xiaoming's store. At this time, considering "Xiao Ming's feelings", Xiaotu software should notify Xiao Ming, but how to do it? Now that the "connection is broken", this matter may not be so easy

In order for the Xiaotu software to easily notify Xiao Ming, it is also necessary for Xiao Ming to re-establish the "connection" with the Xiaotu software. This is the second redirection I saw. After Xiaoming authorized it, he was redirected back to the address of Xiaotusoft, so that Xiaoming had a new "connection" with Xiaotusoft.

At this point, you should be able to understand why you need to redirect twice in the authorization code permission process

In order to re-establish such a connection without exposing the access token, there is such a temporary and indirect credential: the authorization code. Because what Xiaotusoft ultimately needs to obtain is an access token that requires extremely high security and confidentiality, not an authorization code, which can be exposed on the browser. In this way, with the participation of the authorization code, the access token can be transmitted between back-end services, and at the same time, the "connection" between Xiaoming and Xiaotu software can be re-established. In this way, through an authorization code, it not only "takes care" of Xiaoming's experience, but also "takes care" of the security of communication

Now, you should know why there is an authorization code.

Then, when the authorization code process is executed, how do the authorization code and access token flow between Xiaotu software and the authorization service?

2.2 Communication process of authorization code license type

There are 9 steps identified in the communication process of the sequence diagram above. It may seem complicated to analyze step by step, so here we use another dimension to analyze to help understand, that is, from the dimension of direct communication and indirect communication. analyze. The so-called indirect communication here refers to the interaction of obtaining the authorization code, and the direct communication refers to the interaction of exchanging the authorization code for the access token

Next, first analyze which ones are indirect communication and which ones are direct communication?

2.2.1 Indirect communication

First analyze why it is "indirect"

Zoom in on the process of obtaining the authorization code code in the previous sequence diagram, and look at it from another angle, that is, put the browser agent between the third-party software Xiaotu and the authorization service, as shown in the following figure:

insert image description here

This process seems to have such a dialogue:

Xiao Ming: "Hi, Xiaotusoft, I want to visit you"

Xiaotusoft: "Okay, I will direct you to the authorization service, I need the authorization service to give me an authorization code"

Authorization service: "Xiaotusoft, I have sent the authorization code to the browser"

Xiaotu software: "OK, I got the authorization code from the browser"

There is no direct communication between the third-party software Xiaotu and the authorized service, but a "connection" through the "middleman" of the browser. Therefore, it can be said that this is a way of indirect communication

2.2.2 Direct communication

Then "enlarge" the process of obtaining the access token in the previous sequence diagram, and the following diagram is obtained:

insert image description here

Compared with the indirect communication in the process of obtaining the authorization code, the direct communication of obtaining the access token is easier to understand, that is, after the third-party software Xiaotu obtains the code value of the authorization code, it initiates a communication request to the authorization service to obtain the access token access_token. This request is the communication between the third-party software server and the authorized service server. It is a request and response between back-end servers, so it is also called back-end communication.

2.2.3 Two "groups"

After understanding the above communication methods, you can realize that the four roles in OAuth 2.0 are "two-two teams": the resource owner and the third-party software "stand together", because the third-party software must represent the resource owner to Access to protected resources; the authorization service and the protected resource "stand together" in that the authorization service is responsible for issuing access tokens and the protected resource is responsible for receiving and validating access tokens

insert image description here

Speaking of this, you may find that when introducing the authorization code process, it is based on the scenario of browser participation, so must the browser participate in this process? In fact, the authorization code licensing process does not necessarily require the participation of the browser.

2.3 Do I have to have a browser?

At the beginning of the development of OAuth 2.0, the open ecological environment was relatively weak, and most of the web applications were proxyed by browsers. The authorization code permission type was "naturally" applied to web applications that can only be accessed through browsers.

But in fact, OAuth 2.0 is an authorization concept, or an authorization thinking. Its thinking of the authorization code model can be transplanted to many scenarios, such as WeChat applets. When developing WeChat applet applications, the user login information is obtained through the authorization code mode, which is given in the address example of the official document grant_type=authorization_code, and the browser is not used

According to the WeChat official documentation, the process for developers to obtain user login status information is exactly the authorization process of an authorization code:

First, the developer obtains the code value of the login credential through wx.login(Object object)the method . The process of this step is realized by calling the SDK provided by WeChat inside the applet.

Then, the code value is exchanged for the user's session_key and other information, which is auth.code2Sessionthe method , and this method is also strongly recommended to be called through the developer's backend service

It can be seen that this process does not use the browser, but it does go through a complete authorization code licensing process according to the idea of ​​authorization code licensing. That is to say, first obtain the code value through the front end of the applet, and then use the code value to exchange session_key and other information through the backend service of the applet, but the value of the access token access_token is replaced by session_key

This whole process embodies the idea of ​​authorization code licensing process

2.4 Summary

1. There are two communication methods in the authorization code licensing process. One is front-end communication, because it facilitates the interaction process of the authorization code through the browser. For example, the authorization service of the Jingdong Merchant Open Platform generates an authorization code and sends it to the browser, and the third-party software Xiaotu obtains the authorization code from the browser. Just because there is no direct connection between Xiaotu software and the authorization service when obtaining the authorization code, it is also called indirect communication. The other is back-end communication. After Xiaotu software obtains the authorization code, the back-end service directly initiates a request for an access token, which is also called direct communication.

2. In OAuth 2.0, the access token is required to have extremely high security and confidentiality, so it cannot be exposed to the browser, and can only be obtained and used through the back-end service of third-party software (such as Xiaotu). To maximize the security of the access token. Because of the security requirements of the access token, OAuth 2.0 provides a temporary credential: the authorization code when front-end communication is required, such as the transfer on the browser. Through the authorization code, the user Xiaoming can return to the operation page of Xiaotu after authorizing Xiaotu on the authorization service. In this way, under the condition of ensuring safety, Xiaoming's experience on Xiaotu is improved

It can be seen from the authorization code permission process that it perfectly organizes the four roles of OAuth 2.0 and ensures smooth communication between them. The structure and ideas it proposes can be migrated to other environments or protocols, such as using authorization code licenses in WeChat applets

3. Authorization Services

In one sentence, the authorization service is the service responsible for issuing access tokens. Furthermore, the core of OAuth 2.0 is the authorization service, and the core of the authorization service is the token

Why do you say that? When a third-party software such as Xiaotu wants to obtain Xiaoming’s order in JD.com, it must first obtain an access token from the authorization service of JD’s merchant open platform, and then use the access token to “represent” Xiaoming to request Xiaoming’s order data. Isn't this the core of the entire OAuth 2.0 authorization system?

So, how does the authorization service generate an access token, and what operations are involved in it? Another question is, how to regenerate the access token when the access token expires and the user is not present?

3.1 Working process of authorization service

Before starting, let’s recall the whole process of Xiaoming authorizing the order data for Xiaotu software

Xiaotu software first asks Xiaoming to go to the open platform of Jingdong merchants to authorize data for it. Does it feel a bit strange here? You can't say, "Hey, Jingdong, you can give the data to Xiaotu", then Jingdong will definitely reply, "Xiaoming, who is Xiaotu? One is a liar?"

Therefore, the premise of authorizing this big action must be that Xiaotu must go to the platform for "recording", that is, registration. After registration, JD Merchant Open Platform will give Xiaotu software app_id and app_secret and other information to facilitate various identity verification during subsequent authorization

At the same time, when registering, third-party software will also request the accessible range of protected resources. For example, can Xiaotu get the orders from Xiaoming's store 3 months ago, can he get all the field information of each order, and so on. This scope of authority is scope. Regarding the registered data storage, use the following Java code to simulate:

Map<String,String> appMap = new HashMap<String, String>(); // 模拟第三方软件注册之后
appMap.put("app_id", "APPID_RABBIT");
appMap.put("app_secret", "APPSECRET_RABBIT");
appMap.put("redirect_uri", "http://localhost:8080/AppServlet-ch03");
appMap.put("scope", "nickname address pic");

Once you have your case in place, move on. Xiao Ming came over and asked the platform to give Xiaotu his order data. The platform clicked to check, and after confirming the password, he found that Xiaotu was legal, so he was about to move on to the next step.

As mentioned above, in the authorization code license type, the work of the authorization service can be divided into two parts, one is to issue the authorization code code, and the other is to issue the access token access_token. In order to better express the existence of authorization codes and access tokens, they are marked in dark colors in the following figure:

insert image description here

1. First look at the process of issuing the authorization code code

In this process, the authorization service needs to complete two parts of work, namely preparation and generation of authorization code code

What does this "preparation" include? When Xiao Ming authorizes the third-party software Xiaotu Ordering Software, he will see an authorization button on the authorization page, but the authorization service has actually done a series of actions before Xiao Ming sees the authorization button.

These actions are the so-called preparations, including the three steps of verifying basic information, verifying the scope of authority (for the first time) and generating an authorization request page

  1. Verification of basic information, including the verification of the legitimacy of the third-party software Xiaotu and the callback address
    In the web browser environment, the entire request process of issuing code is completed by the browser through front-end communication, which means Information is at risk of being impersonated. Therefore, the authorization service must judge the existence of third-party software

    Similarly, the callback address can also be forged. For example, criminals disguise it as a phishing page, or a malicious software download page. Therefore, from the perspective of security, the authorization service needs to do a basic check on the callback address

    if(!appMap.get("redirect_uri").equals(redirectUri)){
          
          
        //回调地址不存在
    }
    

    In the authorization service program, after the two-step verification is passed, a page ( belonging to the authorization server ) will be generated or responded to prompt Xiaoming to authorize

  2. Verify the permission scope (for the first time)
    since it is authorization, it will involve the scope. For example, when you use WeChat to log in to third-party software, you will see WeChat prompting us that the third-party software can obtain your nickname, avatar, gender, geographical location, etc. If you don't want third-party software to obtain some of your information, you don't need to select this item. The same is true in Xiaotu. When Xiaoming authorizes Xiaotu, he can also choose the scope of authority for Xiaotu, such as whether to grant Xiaotu access to orders 3 months ago

    This means that it is necessary to compare the scope parameter passed by Xiaotu with the permission scope applied for when Xiaotu registered. If the scope of authority requested is greater than the scope of registration, it is necessary to issue a reminder of exceeding authority. Remember, this is the first permission verification

    String scope = request.getParameter("scope");
    if(!checkScope(scope)){
          
          
        //超出注册的权限范围
    }
    
  3. Generate an authorization request page
    The authorization request page is the page on the authorization service, as shown in the following figure:

    insert image description here

    The page shows the two permissions of today and history that Xiaotu applied for when he registered. Xiaoming can choose to narrow the scope of this permission, for example, only grant the permission to obtain today information

    At this point, the preparation for issuing the authorization code code is completed. Note that this is preparatory work, because when the user clicks the authorization button "approve", the authorization code code value and the access token acces_token value will be generated, "everything really starts"

    It needs to be explained here: In the above preparation process, the login process of Xiao Ming was ignored, but only after the user logs in can the third-party software be authorized, and the authorization service can obtain user information and finally generate code and app_id (third-party software The corresponding relationship between the application ID) + user (resource owner ID)

    After Xiaoming clicks the "approve" button, the process of generating the authorization code code officially begins, mainly including the three steps of verifying the scope of authority (the second time), processing the authorization request to generate the authorization code code, and redirecting to the third-party software.

  4. Verify the scope of authority (the second time)
    In step 2, the first verification performed by the authorization service before generating the authorization page is to compare the scope of authority requested by Xiaotu with the authority at the time of registration. The scope of authority for the second verification here is to use Xiaoming to authorize the authority, and then verify it with the authority registered by Xiaotu software

    Why do we need to check again here? Because this is equivalent to a user's input authority. Xiaoming has chosen a certain scope of authority to authorize services, and he must pay attention to the verification of authority, and all input data will involve legality checks. In addition, this is also a good habit of cultivating a request for input data on the server side, and doing a legality check as much as possible

    String[] rscope =request.getParameterValues("rscope");
    if(!checkScope(rscope)){
          
          
        //超出注册的权限范围
    }
    
  5. Process the authorization request and generate the authorization code code.
    After Xiaoming agrees to the authorization, the authorization service will verify the value of the response type response_type. response_type has two types of values: code and token. The authorization code flow is used as an example here, so the code needs to verify whether the value of response_type is code

    String responseType = request.getParameter("response_type");
    if("code".equals(responseType)){
          
          
    }
    

    In the authorization service, the generated authorization code value needs to be mapped with app_id and user. That is to say, an authorization code code means that a certain user authorizes a certain third-party software, for example, Xiaoming authorizes Xiaotu software. At the same time, the code value and this mapping relationship need to be saved for use when generating the access token access_token

    String code = generateCode(appId, "USERTEST"); // 模拟登录用户为USERTEST
    private String generateCode(String appId, String user) {
          
          
        ...
        String code = strb.toString();
        codeMap.put(code,appId+"|"+user+"|"+System.currentTimeMillis());
        return code;
    }
    

    After the authorization code code is generated, the mapping relationship of the response is also bound as described above. But the authorization code mentioned before is a temporary, one-time certificate, so it is also necessary to set an expiration date for the code

    The OAuth 2.0 specification recommends that the authorization code value is valid for 10 minutes, and an authorization code can only be used once. However, according to experience, the validity period of the code in the production environment generally does not exceed 5 minutes

    At the same time, the authorization service also needs to bind and store the generated authorization code code with the authorized scope rscope, so that when the access token is issued later, the authorization scope can be taken out through the code value and bound to the access token. Because third-party software ultimately requests protected resources through access tokens

    Map<String,String[]> codeScopeMap = new HashMap<String, String[]>();
    codeScopeMap.put(code,rscope); // 授权范围与授权码做绑定
    
  6. Redirect to third-party software
    After generating the code value of the authorization code, the authorization service needs to inform the third-party software of the code value to Xiaotu. It was mentioned at the beginning that the issuance of the authorization code code is done through front-end communication, so the redirection method is used here. The redirection of this step is also the second redirection mentioned before

    Map<String, String> params = new HashMap<String, String>();
    params.put("code",code);
    String toAppUrl = URLParamsUtil.appendParams(redirectUri,params); // 构造第三方软件
    response.sendRedirect(toAppUrl); // 授权码流程的“第二次”重定向
    

At this point, the process of issuing the authorization code code is complete. After Xiaotu obtains the value of the authorization code code, it can start requesting the value of the access token access_token

2. Issue access token access_token

The generation process of the authorization code code was introduced earlier, but Xiaotu finally needs to obtain the access token access_token before he can request protected resources. The authorization code is just a temporary credential in exchange for the access token access_token

When Xiaotu makes a request with the authorization code code, the authorization service needs to generate the final request access token for it. This process mainly includes three steps: verifying whether the third-party software Xiaotu exists, verifying whether the code value is legal, and generating an access_token value

  1. Verify the existence of third-party software
    At this point, the type of grant_type received is authorization_code

    String grantType = request.getParameter("grant_type");
    if("authorization_code".equals(grantType)){
          
          
    }
    

    Since the issuance of the access token is done through back-end communication, in addition to verifying the app_id, the app_secret must also be verified here

    if(!appMap.get("app_id").equals(appId)){
          
          
        // app_id不存在
    }
    if(!appMap.get("app_secret").equals(appSecret)){
          
          
        // app_secret不合法
    }
    
  2. Verify that the code value of the authorization code is legal.
    The authorization service has stored the code value at the stage of issuing the authorization code code. At this time, compare the code value received from the request with the code value retrieved from the storage.

    String code = request.getParameter("code");
    if(!isExistCode(code)){
          
           // 验证code值
        // code不存在
        return;
    }
    codeMap.remove(code); // 授权码一旦被使用,须立即作废
    

    It must be remembered here that after confirming that the authorization code value is valid, the current code value should be deleted from the storage immediately to prevent third-party software from maliciously using a stolen authorization code value to request authorization services

  3. Generate the value
    of access token access_token Regarding the rules to generate the value of access token access_token, there is no clear regulation in the OAuth 2.0 specification, but three principles must be met: uniqueness, discontinuity, and unguessability. UUID is used here as an example

    Like the value of the authorization code code, the value of the access token access_token needs to be stored and mapped with the application identifier app_id of the third-party software and the resource owner identifier user. In other words, an access token access_token indicates that a certain user authorizes a certain third-party software

    At the same time, the authorization service also needs to bind the authorization scope with the access token access_token. Finally, you also need to set an expiration time expires_in for the access token, such as 1 day

    Map<String,String[]> tokenScopeMap = new HashMap<String, String[]>();
    String accessToken = generateAccessToken(appId, "USERTEST"); // 生成访问令牌access_token
    tokenScopeMap.put(accessToken,codeScopeMap.get(code)); // 授权范围与访问令牌绑定
    // 生成访问令牌的方法
    private String generateAccessToken(String appId,String user) {
          
          
        String accessToken = UUID.randomUUID().toString();
        String expires_in = "1"; // 1天时间过期
        tokenMap.put(accessToken, appId+"|"+user+"|"+System.currentTimeMillis()+"|"+expires_in);
    
        return accessToken;
    }
    

Just because the OAuth 2.0 specification does not constrain the generation rules of the content of the access token, there is a higher degree of freedom. It is possible to generate a UUID form of data and store it as in the Demo above, so that the authorization service and protected resources can share the data; it is also possible to put some necessary information into the token itself through structured processing. A token that contains some information is called a structured token, or JWT for short.

So far, the two main processes of authorization services under the authorization code license type, that is, the process of issuing authorization codes and issuing access tokens, have been finished.

At this point, you may also notice a problem. When the access token is generated, an expiration time expires_in is attached to it, which means that the access token will expire after a certain period of time. The invalidation of the access token means that the resource owner's authorization to the third-party software is invalid, and the third-party software cannot continue to access the resource owner's protected resources.

At this time, if you still want to continue to use the third-party software, you can only click the authorization button again. For example, after Xiaoming authorized Xiaotu software, he was happily processing the order data of his store. Let Xiaoming authorize again

Obviously, such a user experience is very bad. For this reason, OAuth 2.0 introduces the concept of refresh token, which is to refresh the value of access token access_token. This means that with the refresh token, the user can continue to use the third-party software without clicking the authorization button again within a certain period of time

3.2 Refresh Token

The refresh token is also used by third-party software, and it also needs to follow the principle of issuing first and then using it

3.2.1 Issuing Refresh Tokens

In fact, the issuance of refresh tokens and the issuance of access tokens are implemented together, and they are both generated in the generation of access token access_token in step 3 of process 2. That is to say, when the third-party software gets an access token, it also gets a refresh token:

Map<String,String> refreshTokenMap = new HashMap<String, String>();
String refreshToken = generateRefreshToken(appId, "USERTEST"); // 生成刷新令牌refreshToken
private String generateRefreshToken(String appId,String user) {
    
    
    String refreshToken = UUID.randomUUID().toString();
    refreshTokenMap.put(refreshToken, appId+"|"+user+"|"+System.currentTimeMillis());
  
    return refreshToken;
}

Why generate access token and refresh token together?

This comes back to what refresh tokens do. The original purpose of the refresh token is to re-generate a new access token through the system in order to prevent users from frequently manually authorizing when the access token is invalid. Then, if the access token expires, and there is no refresh token available "around", wouldn't it be troublesome for the user to authorize manually. So, it has to be generated with the access token

3.2.2 Using Refresh Tokens

In the OAuth 2.0 specification, the refresh token is a special authorization permission type, which is embedded under the authorization code permission type. In the code of the authorization service, when receiving such an authorization request, it will first compare the values ​​of grant_type and refresh_token, and then proceed to the next step. The process mainly includes the following two steps:

1. Receive refresh token request

At this time, the grant_type value in the request is refresh_token

String grantType = request.getParameter("grant_type");
if("refresh_token".equals(grantType)){
    
    
}

Like the verification process before issuing an access token, it is also necessary to verify the existence of third-party software. It should be noted that it is necessary to verify the existence of the refresh token at the same time, the purpose is to ensure the legitimacy of the refresh token passed

String refresh_token = request.getParameter("refresh_token");
if(!refreshTokenMap.containsKey(refresh_token)){
    
    
    // 该refresh_token值不存在
}

Also, verify that the refresh token belongs to that third-party software. The authorization service binds the issued refresh token with the third-party software and the authorized user at that time, so here it is necessary to judge the legality of the refresh token

String appStr = refreshTokenMap.get("refresh_token");
if(!appStr.startsWith(appId+"|"+"USERTEST")){
    
    
    // 该refresh_token值不是颁发给该第三方软件的
}

It should be noted that after a refresh token is used, the authorization service needs to discard it and reissue a refresh token

2. Regenerate the access token

The process of generating an access token is consistent with the process of issuing an access token. The authorization service will return the new access token and the new refresh token together to the third-party software

3.3 Summary

1. The core of the authorization service is to first issue the value of the authorization code code, and then issue the value of the access token access_token

2. A refresh token refresh_token value will be issued at the same time as the access token is issued. This mechanism can be used to generate a new access token without user participation

3. Authorization must also have a scope of authorization. Third-party software cannot be allowed to obtain authorizations that are greater than the scope of authorization at the time of registration, nor can it obtain authorization beyond the scope of user authorization. Always ensure the principle of least privilege security

4. JWT structured token

4.1 Introduction

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact, self-contained way to securely transmit information between parties as JSON objects

To understand simply, JWT is a technology for generating tokens in a structured way. The structured token can be endowed with very rich meanings, which is the biggest difference between it and the original meaningless, random string token

After structuring, the token itself can be "stuffed" with some useful information, such as the information that Xiao Ming has authorized Xiaotu software, the scope of authorization information, and so on. Or, it can be visually understood as a kind of "self-encoding" ability, which is precisely what unstructured tokens do not have

The structured body of JWT can be divided into three parts: HEADER (header), PAYLOAD (data body) and SIGNATURE (signature). The overall structure of the signed JWT is three pieces of content separated by period symbols, and the structure is header.payload.signature. For example, the following example ( there is no line break inside the JWT, and it is represented by three lines only for the convenience of display ):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJVU0VSVEVTVCIsImV4cCI6MTU4NDEwNTc5MDcwMywiaWF0IjoxNTg0MTA1OTQ4MzcyfQ.
1HbleXbvJ_2SW8ry30cXOBGR9FW4oSWBd3PWaWKsEXE

This JWT token looks meaningless, it is just a random string. Indeed, it is meaningless to look at this string directly, but if you copy it to the online verification tool of the https://jwt.io/ website , you can see the decoded data:

insert image description here

Looking at the decoded data again, it is obvious that what is presented now is the structured content

JWT mainly includes three parts, HEADER (header), PAYLOAD (payload), SIGNATURE (signature)

HEADER means to load information such as token type and algorithm, which is the header of JWT. Among them, typ indicates that the second part of PAYLOAD is JWT type, and alg indicates the algorithm using HS256 symmetric signature

PAYLOAD represents the data body of JWT, which represents a set of data. Among them, sub (the subject of the token, generally set as the unique identifier of the resource owner), exp (the expiration time stamp of the token), and iat (the time stamp of the token issuance) are JWT normative statements, representing the regular sexual manipulation. For more general declarations, refer to RFC 7519 Open Standard. However, all legal data in JSON format can be included in a JWT, that is to say, a set of data represented by PAYLOAD allows custom declarations

SIGNATURE represents the signature of the JWT information. So, what does it do? You may think that with the two parts of HEADER and PAYLOAD, the token can carry information, and it seems that it can be transmitted in the network, but it is not safe to transmit such information in the network. Therefore, it also needs to be encrypted and signed, and SIGNATURE is the result of signing the information. When the protected resource receives the signature of the third-party software, it needs to verify whether the signature of the token is legal.

Details can be found at: JWT Summary_Fan223's Blog

4.2 Token internal inspection

The authorization service issues the token, and the protected resource service validates the token. At the same time, the authorization service and the protected resource service are "a group" (see 2.2.3), and the protected resource calls the verification token service provided by the authorization service. This way of verifying the token token check

Sometimes the authorization service depends on a database, and then the protected resource service also depends on this database, which is often called a "shared database". However, in today's mature distributed and microservice environment, different systems rely on services instead of databases to communicate. For example, the authorization service provides an RPC service for the protected resource service. As shown below:

insert image description here

Then, after having the JWT token, there is another option, because the JWT token itself contains the information that can only be obtained by relying on the database or RPC service, such as which user mentioned above for which software Authorization and other information

4.3 How is JWT used?

The communication method after having the JWT token, as shown in the figure below, the authorization service "throws" a token, the protected resource service "catches" the token, and then starts to parse the information contained in the token itself. That's it, no need to query the database or request RPC services. This also implements the token internal inspection mentioned above.

insert image description here

In the above picture, in order to better highlight the location of the JWT token, the logical relationship is simplified. In fact, after the authorization service issued the JWT token, it was given to Xiaotu software, and Xiaotu software took the JWT token to request the protected resource service, which is Xiaoming's order in Jingdong store. Obviously, the JWT token needs to be transmitted over the public network. Therefore, during the transmission process, the JWT token needs to be Base64 encoded to prevent garbled characters, and it also needs to be signed and encrypted to prevent data information leakage

If we handle these encodings, encryptions, etc. by ourselves, it will add an additional encoding burden. But we can use some open source tools to help us deal with these tasks. For example, JJWT, Java JWT, the following example uses JJWT

String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth"; // 密钥
Key key = new SecretKeySpec(sharedTokenSecret.getBytes(), SignatureAlgorithm.HS256.getJcaName());
// 生成JWT令牌
String jwts= Jwts.builder().setHeaderParams(headerMap).setClaims(payloadMap).signWith(key, SignatureAlgorithm.HS256.getJcaName());
// 解析JWT令牌
Jws<Claims> claimsJws =Jwts.parserBuilder().setSigningKey(key).build().parseClaims();
JwsHeader header = claimsJws.getHeader();
Claims body = claimsJws.getBody();

When using JJWT to parse the JWT token, it includes the action of verifying the signature. If the signature is incorrect, an exception message will be thrown. This can be used to verify the signature to determine whether it is a legitimate JWT token that has not been forged

4.4 Why use JWT tokens?

1. The core idea of ​​JWT is to use computing instead of storage, which has a "taste" of "time for space". Of course, this calculated and structured encapsulation method also reduces the network transmission consumption caused by the remote call of the "shared database", so it may also save time

2. Another important feature is encryption. Because the JWT token already contains important information, it must be required to be transmitted in ciphertext during the entire transmission process, so that encryption is mandatory to ensure the security of the transmission process. The encryption algorithm here can be either symmetric encryption or asymmetric encryption

3. Using tokens in JWT format helps to enhance the usability and scalability of the system . How to understand this point? This kind of token in JWT format contains the information required for authentication through "self-encoding", and no additional storage is required on the server side, so each request is a stateless session. This is in line with the principle of following the stateless architecture design as much as possible, that is, enhancing the availability and scalability of the system

However, there are two sides to everything, and JWT tokens also have disadvantages. The biggest problem with the JWT format token is that it is "hard to recover", that is, there is no way to modify the state of the token during use. Let’s take Xiaoming’s use of Xiaotu software as an example

When using Xiaotu software, is it possible that Xiao Ming changed his password in Jingdong for some reason, or is it possible that he suddenly canceled the authorization for Xiaotu? At this time, should the status of the token be changed accordingly, and the original corresponding token should be invalidated?

But when using the JWT format token, the token issued each time will not be stored on the server side, so there is nothing you can do when you want to change the status of the token. Because the server does not store the token in JWT format. This means that the JWT token can be "running wild" within the validity period

To solve this problem, is it possible to store the JWT token in a remote distributed in-memory database? Obviously not, because this would defeat the original purpose of JWT (to store information in the token itself in a structured way). Therefore, there are usually two approaches:

  1. The key granularity is reduced to the user level each time a JWT token is generated, that is, one user has one key. In this way, when the user cancels the authorization or changes the password, the key can be changed together. In general, this solution requires a separate key management service
  2. In an environment that does not provide users with active cancellation of authorization, if only changing the password is considered, then the user password can be used as the key of the JWT. Of course, this is also at the user granular level. In this way, changing the password by the user is equivalent to changing the key

4.4 Token Lifecycle

Everything has a cycle, which is a natural law, and tokens are no exception, whether they are JWT structured tokens or ordinary tokens. They all have a validity period, but the JWT token can store the validity period information in its own structure. Specific to the token life cycle of OAuth 2.0, there are usually three situations:

1. The natural expiration process of the token, which is also the most common situation. This process starts from the creation of a token by the authorization service, to the use of the token by third-party software, to the verification of the token by the protected resource service, and finally to the invalidation of the token. At the same time, this process does not rule out the occurrence of active token destruction. For example, if the token is leaked, the authorization service can make the token invalid

2. As mentioned above, after the access token expires, you can use the refresh token to request a new access token to replace the invalid access token, so as to improve the user experience of using third-party software

3. Let the third-party software, such as Xiaotu, initiate a token invalidation request, and then the authorization service will invalidate the token immediately after receiving the request. Under what circumstances will this mechanism be needed, that is, think about the "motivation" of third-party software to do this, after all, under normal circumstances "it is difficult to give up what you already have"

For example, sometimes, there is an ordering relationship between the user and the third-party software. For example, Xiaoming purchased Xiaotu software, then when the subscription period expires or unsubscribes, and the token authorized by Xiaoming has not yet expired, you need to There is such a token revocation protocol to support Xiaotu software to actively initiate a token invalidation request. As a platform party such as Jingdong Merchant Open Platform, it is also recommended that responsible third-party software such as Xiaotu software abide by such a token withdrawal agreement

insert image description here

5. How to access OAuth 2.0 safely and quickly?

In the third section, we have already talked about the process of authorization service. Authorization service takes all the complexity of OAuth 2.0 on itself, which is one of the reasons why authorization service is the core of OAuth 2.0 system.

Although the authorization service does most of the work, in the OAuth 2.0 system, in addition to the resource owner participating as a user, there are two other system roles, that is, third-party software and protected resource services. They should do What kind of work can be connected to the OAuth 2.0 system?

5.1 Building third-party software applications

If you want to build a Xiaotu ordering software application based on the JD Merchant Open Platform, what work should Xiaotu software developers do?

First of all, you need to apply for registration as a developer on the Jingdong Merchant Open Platform, and then create an application after becoming a developer, and then start developing. So, in the process of developing third-party software applications, what should we focus on? These contents include 4 parts, namely: registration information, boot authorization, use of access tokens, and use of refresh tokens

insert image description here

1. Registration information

First of all, Xiaotusoft can only participate in the OAuth 2.0 process if it has an identity. That is to say, Xiaotu software needs to have its own app_id and app_serect information first, and also fill in its own callback address redirect_uri, application permissions and other information

This type of registration is sometimes called static registration, that is, the developers of Xiaotu Software log in to the Jingdong Merchant Open Platform to manually register in advance, so that the relevant information of these registrations can be used later to request access tokens

2. Boot Authorization

When users need to use third-party software to operate their data on protected resources, third-party software is required to guide authorization. For example, if Xiao Ming wants to use the Xiaotu ordering software to print the order delivery in the store, then Xiao Ming must first access the Xiaotu software (in principle, directly access the third-party software, but we will talk about the service market scenario later. , it will be slightly different), it will not be an authorization service, and it will not be a protected resource service

But Xiaotu software needs Xiaoming's authorization, and only the authorized service can allow Xiaoming to do so. Therefore, Xiaotu software needs to "cooperate" with Xiaoming. The first thing to do is to guide Xiaoming to the authorization service, as shown in the following code

What to do then? In fact, it is to allow users to authorize third-party software. After authorization, third-party software can access data on behalf of users. That is to say, only after the Xiaotu ordering software is authorized can it process the order data on behalf of Xiaoming on the Jingdong store.

String oauthUrl = "http://localhost:8081/OauthServlet-ch03?reqType=oauth";
response.sendRedirect(toOauthUrl);

3. Using an access token

To use the token after getting the token is the ultimate goal of the third-party software . Then see how to use the token. At present, OAuth 2.0 tokens only support one type, that is, bearer tokens, that is, tokens that can be in any string format as mentioned earlier

There are three ways to use the access token request given by the official specification, namely:

  1. Form-Encoded Body Parameter (form parameters)

    POST /resource HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded
    access_token=b1a64d5c-5e0c-4a70-9711-7af6568a61fb
    
  2. URI Query Parameter (URI query parameter)

    GET /resource?access_token=b1a64d5c-5e0c-4a70-9711-7af6568a61fb HTTP/1.1
    Host: server.example.com
    
  3. Authorization Request Header Field (authorization request header field)

    GET /resource HTTP/1.1
    Host: server.example.com
    Authorization: Bearer b1a64d5c-5e0c-4a70-9711-7af6568a61fb
    

In other words, all three methods can request protected resource services. So, which method is most suitable?

According to the official recommendation of OAuth 2.0, the request carrier for information transmission before the system accesses OAuth 2.0 is in JSON format, so if you continue to use the form parameter submission method, the token cannot be added because the format does not match. If the method of passing parameters is adopted at this time, the entire URI will be copied as a whole, and the security is the worst. The method of requesting the header field does not have the above-mentioned "annoyances", so the official suggestion is to use the Authorization method to pass the token

However, it is recommended to use form submission, that is, POST, to submit tokens, as shown in the following code. The reason is this. It can also be seen from the official suggestion that before accessing OAuth 2.0, if the request body in JSON data format has been adopted, it is not recommended to use form submission. However, at the beginning, as long as the constraints between the three-party software and the platform are established, and everyone agrees to submit the form, there will be no problem. Because the form submission method ensures secure transmission, it does not need to additionally process the Authorization header information

String protectedURl="http://localhost:8082/ProtectedServlet-ch03";
Map<String, String> paramsMap = new HashMap<String, String>();
paramsMap.put("app_id", "APPID_RABBIT");
paramsMap.put("app_secret", "APPSECRET_RABBIT");
paramsMap.put("token", accessToken);
String result = HttpURLClient.doPost(protectedURl, HttpURLClient.mapToStr(paramsMap));

4. Use refresh token

If the access token expires, Xiaotu software can't immediately prompt and ask Xiao Ming to re-authorize, otherwise Xiao Ming's experience will be very bad. In order to solve this problem, the refresh token is used

The way to use the refresh token is the same as using the access token. For details, please refer to the method of the access token mentioned above. Regarding the use of refresh tokens, the most important thing to care about is when to decide to use refresh tokens

When the Xiaotu software receives the access token, it will also receive the expiration time of the access token expires_in. A well-designed third-party application should save the expires_in value and check it regularly; if it is found that expires_in is about to expire, you need to use refresh_token to re-request the authorization service in order to obtain a new and valid access token

This timing detection method can detect in advance whether the access token is about to expire. In addition, there is a method of "live" discovery. That is to say, for example, when Xiaotu software accesses Xiaoming's store order, it suddenly receives a response that the access token is invalid. At this time, Xiaotu software immediately uses refresh_token to request an access token in order to continue to use his data on behalf of Xiaoming.

On the whole, the timing detection method requires the development of an additional timing task; and "on-site" discovery, there is no such additional workload. Which method to use depends on your actual situation. However, it is still recommended to use the method of regular detection, because it can bring "advanced amount" and have a better initiative, while on-site discovery is a bit passive

Note again that refresh tokens are single-use and will expire after use, but they will have a longer validity period than access tokens. At this time, you may think, what if the refresh token expires? In this case, you need to give up both the refresh token and the access token, which is equivalent to returning to the initial state of the system, and you can only let the user Xiao Ming re-authorize

To sum up, when building third-party applications, you need to focus on registration, authorization, access tokens, and refresh tokens. As long as you master these four parts, it is no longer difficult to develop Xiaotu software on an open platform like JD.com

5.2 Third-Party Application Software in Service Market

When constructing the boot authorization of third-party applications, it is said that the first "touch" by the user must be third-party software, but this is not absolute. This is not absolute, it happens in a scene like the service market

So what is the service market? To put it bluntly, the software you develop, such as Xiaotu ordering software, store decoration software, etc., are released to such a "market" for sale. In this way, after users purchase these software, they can see a "use now" button in the service market. Click this button, users can directly access the third-party software they purchased

For example, there is a "My Service" directory in Jingdong's Jingmai service market, which stores the ordering software I purchased. Xiaoming can directly click "Use Now" to enter Xiaotu ordering software, as shown in the following figure:

insert image description here

Then, what needs to be noted here is that when building third-party software as a third-party developer, in addition to receiving the authorization code code value in the authorization code link, it is also necessary to receive the user's subscription-related information, such as the version number of the service, Service code identification and other information

5.3 Building a protected resource service

In fact, in the entire open authorization environment, protected resources ultimately refer to Web APIs, for example, APIs for accessing avatars and APIs for accessing nicknames. Corresponding to the ordering software, the protected resources are the order query API, batch query API, etc.

The communication between systems on the Internet is basically carried out in the form of Web API. Therefore, when it is said that the protected resources are protected by the authorization service, what is actually said is that the authorization service ultimately protects these Web APIs. When building a protected resource service, besides checking the validity of the token, what else needs to be done? The most important thing is the scope of authority

When processing the logic in the protected resource service, the processing of verifying permissions will occupy a large proportion. When the access token is handed over, it is necessary to see more about what functions the token can operate and what data it can access. Now, to summarize the categories of these permissions, the most common ones are probably as follows:

insert image description here

1. Different permissions correspond to different operations

The operations here actually correspond to Web APIs. For example, the JD Merchant Open Platform currently provides three types of product query APIs, new product APIs, and product deletion APIs. If the scope permission scope of an access token access_token requested by Xiaotu software only corresponds to the query product API and the new product API, then the request containing this access_token value cannot perform the operation of deleting the product API

// 不同的权限对应不同的操作
String[] scope = OauthServlet.tokenScopeMap.get(accessToken);
StringBuffer sbuf = new StringBuffer();
for(int i=0;i<scope.length;i++) {
    
    
    sbuf.append(scope[i]).append("|");
}
if(sbuf.toString().indexOf("query")>0) {
    
    
    queryGoods("");
}
if(sbuf.toString().indexOf("add")>0) {
    
    
    addGoods("");
}
if(sbuf.toString().indexOf("del")>0) {
    
    
    delGoods("");
}

2. Different permissions correspond to different data

The data here refers to the attribute field information contained in an API. For example, there is an API for querying Xiao Ming's information, and the returned information includes Contact (email, phone, qq), Like (Basketball, Swimming), and Personal Data (sex, age, nickname). If the scope permission scope of an access token access_token requested by Xiaotu software only corresponds to Personal Data, then the request containing the access_token value cannot obtain the information of Contact and Like. Regarding this part of the code, it actually corresponds to different permissions The code for different operations is similar to

The granularity of this permission range is smaller than the granularity of "different permissions correspond to different operations". This follows the principle of least privilege scope

3. Different users correspond to different data

This kind of permission is actually just another dimension, positioning it on the user

Some basic information, such as obtaining geographic location, obtaining weather forecast, etc., will not have user attribution attributes, which means that such information does not belong to a certain user and is a type of public information. For such information, the API interfaces provided by the platform are all "neutral" and have no user attributes

However, more scenarios are based on user attributes. Still take the Xiaotu ordering software as an example. Every time a merchant prints a logistics bill, the Xiaotu ordering software must know which merchant's order it is. In this case, the merchant authorizes Xiaotu software, and the access_token obtained by Xiaotu software actually contains the user attribute of the merchant

Every time the protected resource service of Jingdong merchant open platform receives a request from Xiaotu software, it will find the corresponding merchant ID according to the value of access_token in the request, and then query the order information of the merchant according to the merchant ID, that is, different merchants Corresponding to different order data

// 不同的用户对应不同的数据
String user = OauthServlet.tokenMap.get(accessToken);
queryOrders(user);

When talking about the three permissions above, the examples given actually belong to a system that provides all services such as query, add, and delete. At this time, you may think that the current system is already a distributed system environment. If there are many protected resource services, such as user resource services that provide user information queries, product resource services that provide product queries, and order query services. For ordering resource services, shouldn't each protected resource service have to perform the above-mentioned permission range verification, so that there will be a lot of repetitive work?

In order to deal with this situation, there should be a unified gateway layer to handle such verification, and all requests will jump to different protected resource services through API GATEWAY. In this way, there is no need to do permission verification on each protected resource service, but only need to do permission verification at the API GATEWAY layer. The system structure is shown in the figure below:

insert image description here

6. Other License Types

When we talked about the principle and workflow of the authorization code licensing type, I wonder if there is such a question: the authorization code licensing process is the most complete and safest, but is it suitable for all authorization scenarios? Is it too complicated to use the authorization code to authorize in some scenarios, or is it unnecessary at all?

For example, Xiaotu ordering software is a software officially developed by JD. So when Xiaoming uses Xiaotu, does Xiaotu need to go through the authorization code licensing process again? definitely not needed

The characteristic of the authorization code licensing process is that it allows users like Xiaoming to participate through the temporary intermediate value of the authorization code, so as to establish a relationship between Xiaotu software and Jingdong, and then let Xiaotu visit his store in Jingdong on behalf of Xiaoming. order data for

Now that Xiaotu has been "recruited", it belongs to JD.com and is fully trusted by JD. There is no concept of "third-party software". At the same time, Xiao Ming is also the merchant of the Jingdong store, which means that the software and users are the assets of Jingdong. At this time, there is obviously no need to use the authorization code license type for authorization. However, Xiaotu still needs to access the Web API of the order data through the Internet to provide the function of ordering for Xiaoming

Therefore, in order to protect the Web API in these scenarios, and to make OAuth 2.0 better adapt to more scenarios in the real world, to solve cases such as the above-mentioned Xiaotu software, the OAuth 2.0 system also provides resource owner credential permission type

6.1 Resource Owner Credentials Permission

From the name "Resource Owner Credentials Permission", you may already understand its meaning. The resource owner's credentials are the user's credentials, which are username and password. It can be seen that this is the worst way. So why does OAuth 2.0 support this permission type, and is it codified in the OAuth 2.0 specification?

As I mentioned above, Xiaotu is an official software produced by Jingdong at this time, and Xiao Ming is also a user of Jingdong, so Xiaoming can actually use the user name and password to directly use Xiaotu this software. The reason is simply that there is no longer a concept of a "third party" here

But if every time Xiaotu uses Xiaoming's username and password to access Xiaoming's store order data and even product information by calling Web API, in the case of calling so many APIs, it will undoubtedly increase Attack surface for sensitive information such as usernames and passwords

If tokens are used to replace these "flying all over the sky" sensitive information, wouldn't it be possible to protect sensitive information and data to a large extent? In this way, Xiaotu only needs to use the user name and password data once to exchange for a token, and then use the token to access the data of Xiaoming’s store, and will not use the user name and password again in the future, as shown in the following figure:

insert image description here

1. When the user accesses the third-party software Xiaotu, he will be prompted to enter the user name and password. Asking for a username and password is characteristic of the resource owner credential permission type

2. The value of grant_type here is password, which tells the authorization service to request access by using the resource owner's permission credentials.

Map<String, String> params = new HashMap<String, String>();
params.put("grant_type","password");
params.put("app_id","APPIDTEST");
params.put("app_secret","APPSECRETTEST");
params.put("name","NAMETEST");
params.put("password","PASSWORDTEST");

String accessToken = HttpURLClient.doPost(oauthURl,HttpURLClient.mapToStr(params));

3. After the authorization service verifies the user name and password, it generates the value of access_token and returns it to the third-party software

if("password".equals(grantType)){
    
    
    String appSecret = request.getParameter("app_secret");
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    if(!"APPSECRETTEST".equals(appSecret)) {
    
    
        response.getWriter().write("app_secret is not available");
        return;
    }
    if(!"USERNAMETEST".equals(username)) {
    
    
        response.getWriter().write("username is not available");
        return;
    }
    if(!"PASSWORDTEST".equals(password)) {
    
    
        response.getWriter().write("password is not available");
        return;
    }
    String accessToken = generateAccessToken(appId,"USERTEST");//生成访问令牌acc
    response.getWriter().write(accessToken);
}

At this point, you can grasp a piece of information: If the software is officially produced and you want to use OAuth 2.0 to protect the Web API, then you can use Xiaotu software's approach and use the resource owner credential permission type

Whether it is architecture, system or framework, they are dedicated to solving various problems in real production. In addition to the resource owner credential permission type, the OAuth 2.0 system also provides client credential permission and implicit permission types for real-world environments.

6.2 Client Credentials Consent

If there is no clear resource owner, in other words, Xiaotu software has accessed a data that does not require user Xiaoming’s authorization, such as obtaining the image address of JD’s LOGO, this LOGO information does not belong to any third-party user, and other types of third-party software to access the province information provided by the platform, and the province information does not belong to any third-party user

At this point, the role of resource owner is no longer needed in the authorization process. Of course, it can also be vividly understood as "the resource owner is stuffed into the third-party software" or "the third-party software is the resource owner" . The authorization in this scenario is the client credential permission, and the third-party software can directly use the app_id and app_secret at the time of registration to exchange the value of the access token token

insert image description here

In addition, because the authorization process does not involve the resource owner Xiao Ming, the backend service of Xiaotu software can initiate an access_token request at any time, so this kind of authorization does not need to refresh the token

In this way, the key process of the client credential permission type is the following two steps:

1. The third-party software Xiaotu sends a request to the authorization service through the back-end service, where the value of grant_type is client_credentials , telling the authorization service to use the third-party software credentials to request access

Map<String, String> params = new HashMap<String, String>();
params.put("grant_type","client_credentials");
params.put("app_id","APPIDTEST");
params.put("app_secret","APPSECRETTEST");

String accessToken = HttpURLClient.doPost(oauthURl,HttpURLClient.mapToStr(params));

2. After verifying the legitimacy of app_id and app_secret, generate the value of access_token and return

String grantType = request.getParameter("grant_type");
String appId = request.getParameter("app_id");

if(!"APPIDTEST".equals(appId)){
    
    
    response.getWriter().write("app_id is not available");
    return;
}
if("client_credentials".equals(grantType)){
    
    
    String appSecret = request.getParameter("app_secret");
    if(!"APPSECRETTEST".equals(appSecret)){
    
    
        response.getWriter().write("app_secret is not available");
        return;
    }
    String accessToken = generateAccessToken(appId,"USERTEST");//生成访问令牌acc
    response.getWriter().write(accessToken);
}

When obtaining a kind of data that does not belong to any third-party user, it does not require the participation of a user like Xiao Ming, and the client credential permission type can be used at this time

6.3 Implicit License

If the Xiaotu billing software application used by Xiaoming has no back-end service, but is executed in the browser, such as a pure JavaScript application, how should OAuth 2.0 be used?

In fact, the authorization process in this case can use the implicit permission process, which can be understood as the third-party software Xiaotu directly embedded in the browser

In this case, Xiaotu software does not have any confidential data to hide from the browser, and no longer needs the value of the application key app_secret, and no longer needs to exchange the authorization code code for the value of the access token access_token . Because one of the purposes of using the authorization code is to isolate the information of the browser and the third-party software, to ensure that the browser cannot see the value of the most important access token access_token of the third-party software

Therefore, the security of the implicit permission authorization process is much lower. In the authorization process, the Xiaotu software without the server is equivalent to being embedded in the browser, and the process of accessing the browser is equivalent to touching all the Xiaotu software, so the dotted line box is used to represent the Xiaotu software. The entire authorization process is shown in the figure below Show:

insert image description here

1. The user accesses the third-party software Xiaotu through a browser. At this time, the third-party software Xiaotu is actually an application program embedded in the browser

2. This process is similar to the authorization code process, but you need to pay special attention to it. The value of response_type has changed to token, which is to tell the authorization service to return the value of access_token directly. The implicit permission process is the only process that requires the return of access_token in the front-end communication.

Map<String, String> params = new HashMap<String, String>();
params.put("response_type","token"); // 告诉授权服务直接返回access_token
params.put("redirect_uri","http://localhost:8080/AppServlet-ch02");
params.put("app_id","APPIDTEST");
String toOauthUrl = URLParamsUtil.appendParams(oauthUrl,params); // 构造请求授权的Url

response.sendRedirect(toOauthUrl);

3. Generate the value of access_token and return it to the third-party software Xiaotu through front-end communication

String responseType = request.getParameter("response_type");
String redirectUri =request.getParameter("redirect_uri");
String appId = request.getParameter("app_id");
if(!"APPIDTEST".equals(appId)){
    
    
    return;
}

if("token".equals(responseType)){
    
    
    // 隐式许可流程(模拟),DEMO CODE,注意:该流程全部在前端通信中完成
    String accessToken = generateAccessToken(appId,"USERTEST"); // 生成访问令牌accessToken

    Map<String, String> params = new HashMap<String, String>();
    params.put("redirect_uri",redirectUri);
    params.put("access_token",accessToken);

    String toAppUrl = URLParamsUtil.appendParams(redirectUri,params); // 构造第三方
    response.sendRedirect(toAppUrl); // 使用sendRedirect方式模拟前端通信
}

6.4 How to choose?

When connecting to OAuth 2.0, first consider the authorization code permission type, and then choose in combination with the actual production environment:

  1. If Xiaotu software is an official product, you can directly use the resource owner's credential license
  2. If Xiaotu software is an application that is only embedded in the browser and has no server, you can only choose implicit permission
  3. If the information obtained by Xiaotu software does not belong to any third-party user, you can directly use the client credential license type

insert image description here

Among all license types, the security of the authorization code license type is the highest. Therefore, as long as the conditions for using the authorization code license type are met, the authorization code license type must first be

All license types are designed to solve practical problems in reality, so it is necessary to combine the actual production environment and select the most appropriate license type under the premise of ensuring security, such as the rabbit software that uses the client credential license type is a case

7. Using OAuth 2.0 in Mobile Apps

The original application scenario of OAuth 2.0 is indeed a Web application, but its greatness is that it positions its core protocol as a framework rather than a single protocol. The advantage of this is that it can be extended in some specific areas based on this basic framework protocol. Therefore, the OAuth 2.0 protocol is also applicable to desktop or mobile scenarios.

When developing a mobile app, you can choose a "pure app" architecture without a server. For example, this app does not need to communicate with its own server, or can call other open HTTP interfaces; of course, you can also choose a server-side architecture. , for example, this app also wants to record the user's operation log and save it in the server-side database

So to sum it up, mobile apps can be divided into two categories, one is App applications without Server side, and the other is App applications with Server side

insert image description here

The biggest difference between these two types of apps when using OAuth 2.0 lies in the way of obtaining access tokens:

  • If there is a server side, it is recommended to interact with the authorization service through the server side in exchange for an access token
  • If there is no server side, then the only way to interact with the authorization service is through front-end communication, such as the implicit permission authorization type mentioned above. Of course, the security of this method is greatly reduced.

7.1 App without Server

In a pure App application without server-side support, the first thing that comes to mind is, how can requests and responses "come and go" like Web services?

You may think, is it possible to embed a "mini" web server into the App, so that you can use OAuth 2.0 like a web application? Indeed, it works and there are already apps that do it

Such an app can achieve the same communication mechanism as a normal web application by listening to the web server URI running on localhost. But this method is not the focus, because when using this method, the app_secret required when requesting an access token can only be saved on the user's local device, which is not recommended

The key to the problem is how to save the app_secret, because the App will be installed on thousands of terminal devices, once the app_secret is cracked, it will cause disastrous consequences. At this time, some students suddenly thought that if app_secret is not used, the access token access_token can be exchanged in the authorization code process, isn't it all right?

It is indeed possible, but new problems have also come. In the process of the authorization code permission type, if there is no protection of the app_secret layer, then when the authorization code code is exchanged for the access token, only the authorization code code is "charging". At this time, once the authorization code code is stolen, it will bring serious security problems. So, is there any good way to prevent the authorization code from being stolen without using app_secret?

There is such a guiding method in OAuth 2.0. This method is the PKCE protocol, and its full name is Proof Key for Code Exchange by OAuth Public Clients. In the flow chart below, in order to highlight the communication process between the third-party software and the authorization service when using the PKCE protocol, the protected resource service and The role of the resource owner:

insert image description here

First, the app needs to generate a random string verification code with a length between 43 and 128 characters and the parameter code_verifier; then, use this code_verifier to generate a parameter code_challenge called "challenge code"

So how to generate the value of this code_challenge? There are two methods given in the OAuth 2.0 specification, which is to look at the value of the parameter code_challenge_method:

  • code_challenge_method=plain, then the value of code_verifier is the value of code_challenge
  • code_challenge_method=S256, is to encode the code_verifier value in ASCII and then hash it, and then encode the hashed value with BASE64-URL, as shown in the following code:
    code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
    

There are two steps in the authorization code process. The first step is to obtain the authorization code code, and the second step is to use app_id+app_secret+code to obtain the access token access_token. The "dream" just now is to not use app_secret, but at the same time ensure the security of the authorization code process. The two parameters code_verifier and code_challenge are to realize this "dream"

When obtaining the authorization code code in the first step, use the code_challenge parameter. It should be noted that the code_challenge_method parameter must also be passed in the past, the purpose is to let the authorization service know whether the method of generating the code_challenge value is plain or S256

https://authorization-server.com/auth?
response_type=code&
app_id=APP_ID&
redirect_uri=REDIRECT_URI&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256

When obtaining the access token in the second step, use the code_verifier parameter, and the authorization service will perform an operation on the value of code_verifier at this time. How does it work? It is the way of code_challenge_method=S256 above

When requesting the authorization code in the first step, the authorization service has been told how to generate the code_challenge. Therefore, in the process of the second step, the authorization service compares the calculated value with the value received in the first step, and issues an access token if they are the same

POST https://api.authorization-server.com/token?
grant_type=authorization_code&
code=AUTH_CODE_HERE&
redirect_uri=REDIRECT_URI&
app_id=APP_ID&
code_verifier=CODE_VERIFIER

To sum up, when exchanging the authorization code code, use the code_challenge parameter value; when exchanging the access token, use the code_verifier parameter value. So, why do you want to do this?

Our wish is that the authorization code authorization process can also be used without the mobile app on the server side. app_secret cannot be used because it can only be stored on the user's device and is worried about being leaked

Then, without the protection of app_secret, even if the authorization code code is intercepted and the code_challenge is intercepted at the same time, there is no way to deduce the value of code_verifier from code_challenge. And just when the access token is exchanged in the second step, what the authorization service needs is the value of code_verifier. Therefore, this also avoids the security problem that the access token is exchanged maliciously

Now, with the help of the PKCE protocol, apps without a server can safely use the authorization code license type for authorization. However, as recommended by the OAuth 2.0 specification, it is more secure to communicate through the backend in exchange for an access token. So there is really no need for a Server side? When doing mobile application development, did you really decide to abandon the server side from the design?

7.2 App with Server

If the developer has accessed WeChat login, you will see the following sentence on the official WeChat document:

WeChat OAuth 2.0 authorization login currently supports authorization_code mode, which is suitable for application authorization with Server side

WeChat's OAuth 2.0 authorized login suggests that a server is required to support such authorized access. Then, how does an App with server support use the OAuth 2.0 authorization code permission process? Take WeChat login as an example:

insert image description here

Seeing this picture, it is no different from the ordinary authorization code process. It is still a two-step strategy: the first step is to exchange the authorization code code, and the second step is to exchange the authorization code code for the access token access_token

The third-party application here is the application developed by us as a developer, including mobile App and server. "Zoom in" to get the following picture:

insert image description here

From this "enlarged" picture, you will find that there is almost no difference between the server-side app and the ordinary web application when using the authorization code process

The approximate process is: when we access a third-party app, we need to use WeChat to log in; the third-party app can pull up the WeChat app, and we will log in and authorize it in the WeChat app; the WeChat server will return after successful verification An authorization code code is passed to the third-party app through the WeChat App; the subsequent process is to use the authorization code code and app_secret in exchange for the value of the access token access_token

When using app_secret this time, we use it on the server side of the third-party app, so there is no problem in security

8. Security breaches

"Isn't OAuth 2.0 a security protocol, isn't it for protecting Web APIs? Why does OAuth 2.0 itself have security issues?"

First, OAuth 2.0 is indeed a security protocol. This is not a problem, but it has many usage specifications, such as the authorization code is a temporary credential that can only be used once, and the redirection URI needs to be verified. Then, if it is not implemented according to such specifications when using it, there will be security holes

Secondly, since OAuth 2.0 "grows" in the big environment of the Internet, it will also face attacks of common security risks on the Internet, such as cross-site request forgery (Cross-site request forgery, CSRF), cross-site scripting attack (Cross-site Site Scripting, XSS)

Finally, in addition to these common types of attacks, OAuth 2.0 itself has security vulnerabilities that can be exploited, such as authorization code theft, redirection URI forgery

8.1 CSRF attack

For the definition of CSRF, the explanation in the book "OAuth 2 in Action" is the most appropriate explanation I have seen so far: Malware allows the browser to initiate a request to a website that has completed user authentication and perform harmful operations , which is a cross-site request forgery attack

Assume that a user has already logged in on a certain software platform and has authorized the software, that is, the user has already logged in on the software platform. If the attacker intercepts the authorization code at this time and constructs a malicious page on his own website, if the user is induced by the attacker to click the malicious page at this time, the result is that the software continues to OAuth after receiving the authorization code. 2.0 process, but the authorized access token access_token and the information obtained through accces_token will belong to the attacker

So how to avoid this attack? The method is also very simple. In fact, there is such a suggestion in OAuth 2.0, which is to use the state parameter, which is a parameter with a random value.

When requesting an authorization code, a self-generated state parameter value is attached, and the authorization service also returns this random state value together with the authorization code code according to the rules. In this way, when the authorization code is received, a comparison and verification of the value of the state parameter must be performed. If the value is the same, the process will continue, otherwise the subsequent process will be rejected directly.

In this case, if you want to launch a CSRF attack again, you must construct another state value, and this state is not so easy to be forged. This is a random value, and when it was generated, it followed the suggestion that the probability of being "guessed" should be extremely small

8.2 XSS attack

The main method of XSS attack is to inject malicious scripts into the input of the request. Attackers can use the injected malicious scripts to carry out attacks, such as collecting data, etc.

When the request arrives at the protected resource service, the system needs to do verification, such as third-party software identity verification, access token access_token verification, if these information cannot be verified, the protected resource service will return wrong information

insert image description here

In most cases, the protected resource is to echo the input content, such as app_id invalid, access_token, and invalid, and then it will be captured by XSS attackers. Just imagine, if an attacker passes in some malicious JavaScript code that collects user data, and the protected resource service directly returns to the user's page, then when the user triggers these codes, they will be attacked

Therefore, the protected resource service needs to repair this kind of XSS vulnerability, and the specific repair method is
similar to that of other websites to defend against XSS. The easiest way is to escape and filter such illegal information, such as including

<script><img><a>

Escaping and filtering information such as labels

8.3 Horizontal override

Horizontal violation means that when requesting protected resource service data, the server application does not verify whether the data belongs to the currently authorized requesting user, so that when the lawless person uses the authorization obtained by himself to access the protected resource service , it is possible to obtain the data of other users, leading to the occurrence of horizontal unauthorized loopholes. Operations that an attacker can override include adding, deleting, modifying, and querying. Both update operations and query operations are quite harmful.

Take "Little Rabbit Ordering Software" as an example, a third-party developer developed this ordering software, which is currently purchased and used by two merchants A and B. Now Xiaotu ordering software provides the function of querying order data according to the order ID, as shown in the figure below:

insert image description here

Merchant A and Merchant B respectively authorize the Xiaotu Ordering Software application, that is to say, Xiaotu Ordering Software can obtain the order data of Merchant A and Merchant B. There is no problem at this point, so can Merchant A get the order data of Merchant B? The answer is, very likely

In an open platform environment, verification of authorization relationships is generally handled by the open gateway layer, because protected resource services are scattered in various business support departments. After the request data passes through the open gateway, the user's identity, such as the merchant ID, is obtained by the access token access_token, and it will be transparently transmitted to the protected resource service, that is, the system of the upstream interface provider

At this time, if the protected resource service does not make an attribution judgment on the merchant ID and order ID, there may be a problem that merchant A obtains merchant B’s order data, resulting in the problem of horizontal overreach

insert image description here

The root cause of the horizontal overreach problem is the lack of cognition and awareness of developers. If cognition and awareness can keep up, then adding affiliation judgment at the beginning of the design, such as the above-mentioned affiliation judgment of order ID and merchant ID, can avoid this loophole to a large extent

At the same time, in an open platform environment, since the open gateway and the data interface provider come from different business departments, the logical processing to prevent level verification is easily missed:

  • On the one hand, the role of the open gateway is to convert the access token access_token information after user authorization into real user information, such as the merchant ID mentioned above, and then pass it to the interface provider. The data attribution judgment logic can only be determined by the interface provider. internal processing
  • On the other hand, the data provider often thinks that the open interface is "called by the system of the same company", and it is easy to ignore the logical processing of level verification

Above, the three types of attacks, CSRF attack, XSS attack, and horizontal unauthorized access, all belong to the common attack types that OAuth 2.0 faces on the Internet. Next, let’s look at two OAuth 2.0-specific security attacks, namely authorization code Stolen, redirect URI tampered with

8.4 Stolen authorization code

If third-party software A has legal app_id and app_secret, then when it requests an access token, it is also legal, and there is no problem at this time

If a user G authorizes the third-party software B and generates an authorization code codeB, but does not authorize the attacker software A. At this time, software A cannot access all data of user G. But at this time, if software A obtains this codeB, can it access user G's data without user G's authorization?

The root of the problem at this time lies in two points:

  • The authorization service did not verify app_id_B when verifying the authorization code
  • After software B used the value of codeB once, the authorization service did not delete this codeB

Seeing this, by verifying app_id_B and deleting the once-used authorization code and its corresponding access token, you can fundamentally eliminate the harm caused by the theft of the authorization code

Speaking of which, you may have to ask, how did the authorization code get stolen?

8.5 Redirect URI has been tampered with

Sometimes, the authorization service provider does not perform integrity requirements and integrity verification on the callback URI of the third-party software. For example, the detailed callback URI of the third software B is https://time.geekbang.org/callback, then in the absence of integrity verification, as long as
https://time.geekbang.orgthe callback URI address starting with is considered legal

At this point, if the hacker is https://time.geekbang.org/page/under , a page hacker.html is created. The content of this page can be very simple, and its purpose is to allow the request to reach the attacker's service

<html>
  <img src ="https://clientA.com/catch">
</html>

The attack process is as follows:

First, the hacker puts the constructed attack page on the corresponding hacker.html, that https://time.geekbang.org/page/hacker.htmlis , and constructs a new redirection URI, namely
https://time.geekbang.org/page/welcome/back.html../hacker.html

Then, hackers use some phishing methods to induce users to click on the following address:

https://oauth-server.com/auth?respons_type=code&client_id=CLIENTID&redirect_uri=https://clientA.com/catch

In this way, when the authorization service responds to the redirection request, the authorization code code is returned to the hacker.html page

Finally, on https://clientA.com/catchthe page will get the user's authorization code by parsing the Referrer header, and then can exchange for the access token as in the scenario where the authorization code is stolen

You can see here that if the callback URI required by the authorization service is https://time.geekbang.org/callback, and the integrity check of the callback URI is done, then the callback address after being tampered with https://time.geekbang.org/page/welcome/back.html../hacker.htmlwill by the authorization service to initiate a redirection request

Strictly speaking, the conditions for such a loophole to occur are relatively harsh. As long as the signature verification is performed when the authorization service verifies the request of the third-party software, the attacker still cannot obtain the access token when only the authorization code code is obtained, because the third-party software can only be accessed through the access token. user data

9. Using OAuth 2.0 to implement an OpenID Connect user authentication protocol

If you are a third-party software developer, when implementing the logic of user login, in addition to allowing users to register a new account and then log in, you can also access platforms such as WeChat and Weibo, allowing users to use their own WeChat and Weibo account to log in. At the same time, if there are multiple sub-applications under your application, you can also allow users to log in once to access all sub-applications to improve user experience

This is federated login and single sign-on. Going further, they are actually the realization of the application scenarios of OpenID Connect (OIDC for short). So what is OIDC?

9.1 What are OIDCs?

OIDC is actually an open standard for user identity authentication. The scenario of using a WeChat account to log in to a third-party app is the practice of this open standard

Speaking of this, you may ask: "Isn't the OAuth 2.0 open protocol used to log in to third-party apps using WeChat? Why is OIDC involved?"

Using WeChat to log in to a third-party software does use OAuth 2.0. But OAuth2.0 is an authorization protocol, not an authentication protocol. OIDC is the identity authentication protocol, and it is an interworking protocol based on OAuth 2.0 to perform user identity authentication. More generally speaking, OIDC is an identity authentication framework protocol directly based on OAuth 2.0. In another way of expression, OIDC= authorization protocol + identity authentication , which is a superset of OAuth 2.0

9.2 Role correspondence between OIDC and OAuth 2.0

The operation of the OAuth 2.0 authorization code licensing process requires smooth communication and cooperation among the four roles of the resource owner, third-party software, authorization service, and protected resources. If you want to build OIDC on the basis of the authorization code permission type of OAuth 2.0, these four roles still need to continue to play "their value". Then, how do these four roles correspond to the participants in OIDC?

So first of all, we must first think about a protocol framework about identity authentication, and what role it should have. It requires an end user who logs in to the third-party software, a third-party software, and an authentication service to provide the user with an identity verification judgment

These are the three main roles of OIDC. In the official standard framework of OIDC, the names of these three roles are:

  1. EU (End User), on behalf of the end user
  2. RP (Relying Party), which represents the relying party of the authentication service, is the third-party software I mentioned above
  3. OP (OpenID Provider), representing the provider of identity authentication services

Now many apps are connected to WeChat login, so WeChat login is a big identity authentication service (OP). Once you have a WeChat account, you can log in to all Apps (RP) connected to the WeChat login system, which is often referred to as joint login. With the example of geek time, let's look at the correspondence between the 4 roles of OAuth 2.0 and the 3 roles of OIDC:

insert image description here

9.3 Key differences between OIDC and OAuth 2.0

Looking at this role correspondence diagram, we can actually see that to implement an OIDC protocol is to directly implement an OAuth 2.0 protocol. OIDC is an identity authentication protocol framework based on OAuth 2.0. The communication flow chart of OIDC is as follows:

insert image description here

It can be found that an OIDC protocol process based on the authorization code process is almost exactly the same as the authorization code licensing process in OAuth 2.0. The only difference is that an additional ID_TOKEN is returned, which is called an ID token. This token is the key to authentication

9.4 ID token generation and parsing method in OIDC

In step 6 of the OIDC communication process in the above figure, you can see that the ID token (ID_TOKEN) and the access token (ACCESS_TOKEN) are returned together. The access token does not need to be parsed by third-party software because it is opaque to third-party software. But the ID token needs to be able to be parsed by third-party software, because the third-party software needs to obtain the content in the ID token to process the user's login status logic

What is the content of the ID token?

First, the ID token is a JWT-formatted token. Although the JWT token is a token with a self-contained information body, it is convenient to use it as an ID token, but because the ID token needs to be able to identify the user, expiration time and other attributes to achieve the purpose of identity authentication, Therefore, when using it as the ID token of OIDC, the following five JWT statement parameters are also necessary:

  • iss, the issuer of the token, whose value is the URL of the authentication service (OP)
  • sub, the subject of the token, whose value is a globally unique identifier that can represent the end user (EU)
  • aud, the target audience of the token, its value is the app_id of the third-party software (RP)
  • exp, the expiration timestamp of the token, all ID tokens will have an expiration time
  • iat, the timestamp at which the token was issued

The sample code for the part that generates the ID token is as follows:

// GENATE ID TOKEN
String id_token=genrateIdToken(appId,user);
private String genrateIdToken(String appId,String user) {
    
    
	String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth"; //秘钥
	Key key = new SecretKeySpec(sharedTokenSecret.getBytes(),
	SignatureAlgorithm.HS256.getJcaName()); // 采用HS256算法
	Map<String, Object> headerMap = new HashMap<>(); // ID令牌的头部信息
	headerMap.put("typ", "JWT");
	headerMap.put("alg", "HS256");
	Map<String, Object> payloadMap = new HashMap<>(); // ID令牌的主体信息
	payloadMap.put("iss", "http://localhost:8081/");
	payloadMap.put("sub", user);
	payloadMap.put("aud", appId);
	payloadMap.put("exp", 1584105790703L);
	payloadMap.put("iat", 1584105948372L);

	return Jwts.builder().setHeaderParams(headerMap).setClaims(payloadMap).signWith();
}

Next, let's look at how the logic for handling user login status is handled

You can first think about it, if you "do not have a relationship with OIDC", that is, if you "simplely" build a user authentication login system, do you have to save the session relationship of user login. The general approach is to either put it on the remote server, or write it into the cookie of the browser, and set an expiration time for the session ID at the same time

However, when there is a structured information body such as JWT, especially after including the subject and expiration time of the token, isn't there a "natural" session relationship information?

Therefore, relying on the ID token in JWT format is enough to solve the login status problem after authentication. This is why the ID token is returned in the OIDC protocol, and the ID token is the key to OIDC as an identity authentication protocol

So with the ID token, how should third-party software parse it? The specific code for parsing the ID token is as follows:

private Map<String,String> parseJwt(String jwt) {
    
    
	String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth";
	Key key = new SecretKeySpec(sharedTokenSecret.getBytes(),
	SignatureAlgorithm.HS256.getJcaName()); // HS256算法
	Map<String,String> map = new HashMap<String, String>();
	Jws<Claims> claimsJws = Jwts.parserBuilder().setSigningKey(key).build();
	// 解析ID令牌主体信息
	Claims body = claimsJws.getBody();
	map.put("sub",body.getSubject());
	map.put("aud",body.getAudience());
	map.put("iss",body.getIssuer());
	map.put("exp",String.valueOf(body.getExpiration().getTime()));
	map.put("iat",String.valueOf(body.getIssuedAt().getTime()));

	return map;
}

It should be pointed out that after the third-party software parses and verifies the legitimacy of the ID token, it does not need to save the entire JWT information, but only the PAYLOAD (data body) part of the JWT. Because it is this part of the content that contains information such as the user's unique identifier required for identity authentication

In addition, when verifying the legitimacy of JWT, because the ID token itself has been signed by the key of the identity authentication service (OP), the key point is that signature verification is required for legitimacy verification

In this way, when the third-party software (RP) gets the ID token, it has already obtained the information for processing the identity authentication action, that is, the ID value that can uniquely identify the end user (EU), such as 3521

9.5 Use access tokens to obtain information other than ID tokens

However, in order to improve the user-friendliness of third-party software, displaying "Hello, 3521" on the page is definitely not as good as displaying "Hello, classmate Xiaoming". The "classmate Xiaoming" here is just the user's nickname

So how to get the nickname "Student Xiao Ming". This is also very simple, just resend the request through the returned access token access_token. Of course, this process is now very familiar, and it belongs to the process of requesting protected resource services in the OAuth 2.0 standard process

This is why in the OIDC protocol, both the ID token and the access token are returned. On the premise of ensuring the user identity authentication function, if you want to obtain more user information, you can obtain it through the access token. In the OIDC framework, this part is called creating UserInfo endpoints and getting UserInfo information

Looking at it this way, the process of fine-grained OIDC is: generate ID token -> create UserInfo endpoint -> resolve ID token -> record login status -> get UserInfo

The most critical way to implement OIDC with OAuth 2.0 is to add ID tokens and UserInfo endpoints on the basis of the original OAuth 2.0 process to ensure that third-party software in OIDC can record user status and obtain user details.

Because the third-party software can record the user status by parsing the key user identification information of the ID token, and at the same time obtain more detailed user information through the Userinfo endpoint. With the user state and user information, it is natural to realize an identity authentication

9.6 Single sign-on

A user G wants to log in to the third-party software A. A has three sub-applications, and the domain names are a1.com, a2.com, and a3.com. If A wants to provide users with a smoother login experience, allowing user G to log in to the other two domains after logging in to a1.com, an identity authentication service can be created to support a1.com, a2.com, and a3 .com login. This is the so-called single sign-on, "one login, all unblocked"

So, can such a single sign-on be implemented using the OIDC protocol standard? As shown in the figure below, you only need to let the third-party software (RP) repeat the OIDC communication process mentioned above.

insert image description here

Single sign-on is a specific application method of OIDC. As long as you master the principle of OIDC framework, it is easy to realize single sign-on

9.7 Summary

1. OAuth 2.0 is not an authentication protocol , so keep this in mind. Identity authentication emphasizes "whose problem", while OAuth2.0 emphasizes authorization, which is a "possible" problem. However, on the basis of OAuth2.0, the user's unique identifier can be obtained by adding an ID token, so that an identity authentication protocol can be implemented

2. Some apps don’t want to take the trouble to design a set of registration and login authentication process by themselves, so they will seek a unified solution, and then there will inevitably be a platform to cover all similar authentication login scenarios. The reverse understanding is also established. If there is an access platform with a large number of users and high traffic to provide a unified login authentication service and allow other third-party applications to connect, it will not be able to solve the problem that a user uses the same account to log in to many third-party apps. Yet? OIDC is an open solution for such a login authentication scenario.

On some larger platforms that already have identity authentication services, you may not find the description of OIDC, but you don't have to worry about it. Sometimes, we may be confused, whether there is a standard like OIDC first, or an identity authentication implementation like WeChat login first?

In fact, to understand this layer of sequence relationship, you can take the design pattern as an example. When you want to design a loosely coupled and extensible system, even if you have never been exposed to design patterns, you will come up with a code architecture idea that gradually conforms to the "smell" of the design pattern after continuous trial and modification. It is the same reason to understand OIDC's idea of ​​solving identity authentication problems

10. Microservice Reference Architecture Based on OAuth 2.0/JWT

The evolution from monolithic to microservice architecture is a major trend in the current digital transformation of enterprises. OAuth 2.0 is the current industry-standard authorization protocol. Its core is several token issuance and management processes for different scenarios; JWT is a lightweight, self-contained token that can be used to securely communicate between microservices. Pass user information

As far as we know, although many companies have partially or fully transformed to the microservice architecture, they are generally customized and self-developed in terms of authorization and authentication mechanisms, such as the token services of Ctrip and Paipaidai. The main reason for customizing and self-developing is that the standard OAuth 2.0 protocol is relatively complicated and the threshold is relatively high. Although customized self-research can temporarily solve enterprise problems, it is not universal and may have many potential security risks

How should the industry standard OAuth 2.0/JWT be integrated with microservices, and is there any reference architecture that can be implemented?

In response to this problem, here is a reference architecture that can be implemented. However, it should be noted in advance that the idea of ​​this architecture comes from the article MICRO-SERVICES ARCHITECTURE WITH OAUTH2 AND JWT –PART 1 – OVERVIEW. According to the description of the original author Thijs, the architecture he proposed has already been implemented in the enterprise

The architecture given by Thijs is indeed practical and of reference value, but the naming of some microservice layers in his architecture, such as BFF and Facade layers, does not match the current mainstream microservice architecture, and his architecture should be hand-painted , is not clear enough and not easy to understand. To this end, let's improve the architecture given by Thijs and supplement the process for different scenarios

Suppose there is such a new retail company called ACME, which has achieved digital transformation, and the microservice e-commerce platform is the core infrastructure to support business operations. In terms of business structure, ACME has nearly a thousand offline stores, and these stores are connected to the e-commerce platform through the POS system. The company also has some logistics and delivery centers, and the order picking system also needs to be connected with the e-commerce platform. In addition, the company also has many delivery drivers who connect with the e-commerce platform through the App. Of course, ACME also has some e-commerce websites for online marketing and sales, and these websites are the main traffic sources of e-commerce platforms

Although the technical platform supporting ACME's business operations is complex, its core can be described with a simplified microservice architecture diagram:

insert image description here

It can be seen that this microservice architecture is running in a Kubernetes cluster. Of course, this architecture does not actually require a Kubernetes environment, and a traditional data center can also be used. In addition, its overall authentication and authorization architecture is implemented based on OAuth 2.0/JWT

10.1 Microservice layered architecture

ACME's microservice architecture can be roughly divided into Nginx reverse proxy layer, Web application layer, Gateway gateway layer, BEF layer and domain service layer, including an IDP service. Generally speaking, this is a current mainstream microservice architecture layering method, and each layer has a single and clear responsibility

1. Nginx reverse proxy layer

First of all, the Nginx cluster is the traffic entrance of the entire platform. Nginx is a 7-layer HTTP reverse proxy. Its main function is to implement reverse routing, that is, to route external traffic to different backends according to the HOST host header or PATH, such as routing to web applications, or directly to the gateway Gateway

In the Kubernetes system, Nginx works with Ingress Controller (entry controller) (collectively referred to as Nginx Ingress). Ingress Controller supports configuring Nginx routing rules through Ingress Rules

2. Web application layer

This layer is mainly some web applications, resources such as html/css/js live in this layer

The Web service layer is usually processed by the traditional Web MVC + template engine method, which can realize server-side rendering or single-page SPA method. This layer is mainly in charge of the company's front-end team, which is usually implemented using the Node.js technology stack, and can also be implemented using the Spring MVC technology stack. How to achieve it depends on which technology the company's front-end team is better at. When this layer needs background data, the background service can be called through the gateway to obtain data

3. Gateway gateway layer

This layer is the entry point for microservice call traffic. The main responsibility of the gateway is reverse routing, that is, routing the front-end request to the back-end target microservice according to the HOST host header, or PATH, or query parameters (for example, IDP/BFF in the figure or directly to the domain service)

In addition, the gateway has two important security responsibilities:

  • One is the verification and conversion of the token. The OAuth 2.0 access token passed by the front end is verified by calling the IDP, and converted into a JWT token containing user and permission information, and then the JWT token is sent to the background microservice transfer
  • The other is permission verification. The routing table of the gateway can be associated with the Scope of OAuth 2.0. In this way, the gateway can judge whether the request has the permission to call the background service according to the permission scope Scope in the request token

In addition, the gateway also needs to undertake functions such as centralized current limiting, log monitoring, and support for CORS

4. IDP service

IDP is the abbreviation of Identity Provider. It is mainly responsible for OAuth 2.0 authorization protocol processing, OAuth 2.0 and JWT token issuance and management, and user authentication. IDP uses the Login-Service in the background for user authentication

For IDP technology selection, the current mainstream Spring Security OAuth, or RedHat's open source KeyCloak, can be considered. Among them, Spring Security OAuth is an OAuth 2.0 development framework, suitable for enterprise customization. KeyCloak is an out-of-the-box OAuth 2.0/OIDC product

5. BFF layer

BFF is the abbreviation of Backend for Frontend. It mainly realizes the aggregation (Aggregation, somewhat similar to database Join) function of backend domain services, and provides more friendly API and data format for different front-end experiences (PC/Mobile/open platform, etc.)

BFF can contain some business logic and even have its own database storage. Usually, BFF needs to call two or more domain services, and may even call other BFFs (of course, it is generally not recommended to call this way, because it will make the calling relationship complicated and incomprehensible)

If BFF needs to obtain information about the calling user or OAuth 2.0 Scope, it can obtain it directly from the passed JWT token

BFF services can be developed with Node.js or Java/Spring and other frameworks.

6. Domain service layer

The domain service layer is at the bottom of the entire microservice architecture. These services contain business logic, usually have their own independent database storage, and can also call external services as needed

According to the principle of microservice layering, domain services are forbidden to call other domain services, let alone reverse calls to BFF services. This is done to keep the single responsibility (Single Responsibility) and bounded context (Bounded Context) of microservices and avoid complex domain dependencies. A domain service is an independent unit of development, testing, and release. In the field of e-commerce, common domain services include user services, commodity services, order services, and payment services.

Like BFF, if the domain service needs to get information about the calling user or OAuth 2.0 Scope, it can get it directly from the passed JWT token

It can be seen that domain services and BFF services are stateless, and they do not store user status themselves, but obtain user information through JWT data passed over. Therefore, in the entire architecture, microservices are stateless and can be scaled horizontally on demand. The state is either stored in the client (browser or mobile app), or stored in a centralized database.

10.2 How does OAuth 2.0/JWT integrate with microservices?

10.2.1 First-Party Web Application + Resource Owner Credentials Mode

This scenario is that the user visits ACME's own e-commerce website, assuming that the e-commerce website is developed with Spring MVC. Considering that this is a first-party scenario (that is, a website application developed by the company), you can choose the Resource Owner Password Credentials Grant of OAuth 2.0, or you can choose the more secure authorization code permission (Authorization Code Grant). Because there is no concept of a third party here, a relatively simple resource owner credential permission is selected.

The following is a sample authentication and authorization flow. Note that this only highlights the key steps. In actual production, there are still many areas that need to be improved and optimized. In addition, for simplicity of description, a successful process is assumed here:

insert image description here

In the above figure, the user corresponds to the resource owner in OAuth 2.0, and ACME IDP corresponds to the authorization service in OAuth 2.0. In addition, the background microservices (including BFF and basic domain services) in the previous architecture diagram correspond to the protected resources in OAuth 2.0. The process description is as follows:

  1. The user visits ACME's e-commerce website through a browser and clicks the login link
  2. The web application returns to the login interface (this login page can be customized and developed by the website itself)
  3. User enters username and password for authentication
  4. The web application forwards the username and password to the token acquisition endpoint of the IDP through the gateway ( POST /oauth2/token,grant_type=password)
  5. IDP authenticates users through Login Service
  6. IDP authentication is passed, and a valid access token is returned (refresh tokens can also be returned as needed)
  7. The web application receives the access token, creates a user Session, saves the OAuth 2.0 token in it, and then
    returns the login success to the client
  8. The session cookie is recorded in the user's browser, and the login is successful

Next, let's take a look at the service invocation process after authentication and authorization. Again, key steps are only highlighted here and assumed to be a successful process

insert image description here

  1. After the user logs in, click on the website to view their shopping history
  2. The web application calls the background API through the gateway (query the user's shopping history), and requests the OAuth 2.0 token (from the user Session) in the HTTP header
  3. The gateway intercepts the OAuth 2.0 token and goes to the IDP for verification
  4. IDP verification token passed, and then query user and Scope information through the token, build JWT token, and return
  5. The gateway obtains the JWT token, checks whether the Scope has permission to call the API, and if so, forwards it to the background API for calling
  6. The background BFF (or domain service) obtains user information through the passed JWT, queries the shopping history according to the user ID, and returns
  7. The web application obtains the user's shopping history data, which can be cached in the Session as needed, and then returned to the client
  8. The shopping history data is returned to the user's browser

This service invocation process can also be applied in other scenarios, such as the "first-party mobile application + authorization code licensing model" and "third-party web application + authorization code licensing model" mentioned later. Basically, as long as you understand the principle of this process, you can flexibly apply it according to the actual scene

10.2.2 First-party mobile application + authorization code licensing model

Users access ACME's own e-commerce App through their mobile phones. This is a first-party native application (Native App) scenario. Usually, the user name and password mode of OAuth 2.0 is considered, but it is not safe (refer to the Security Consideration section of MICRO-SERVICES ARCHITECTURE WITH OAUTH2 AND JWT – PART 3 – IDP), Therefore, the industry recommends using the authorization code mode, and it is necessary to support the PKCE extended authorization code mode

Next, let's take a look at the authentication and authorization process. Again, here are just the key steps highlighted and assumed to be a successful process

insert image description here

  1. The user accesses the e-commerce App and clicks to log in
  2. App generates PKCE related code verifier + challenge
  3. The app starts the mobile browser in an embedded way, visits the unified authentication page of IDP (GET /authorize), and requests to bring the relevant parameters of the PKCE code challenge
  4. IDP returns to Unified Authentication page
  5. User Authentication and Authorization
  6. IDP authenticates users through Login Service
  7. IDP returns authorization code to App browser
  8. The App intercepts the authorization code returned by the browser, and forwards the authorization code + PKCE code verifer to the
    token acquisition endpoint of the IDP through the gateway (POST /oauth2/token, grant_type=authorization-code)
  9. IDP verifies the PKCE and authorization code, and returns a valid access token if the verification passes
  10. App obtains the token, stores it locally, and successfully logs in

Afterwards, if the App needs to interact with the background, it can directly call the background microservice through the gateway, and request an OAuth 2.0 access token in the HTTP header. The subsequent service invocation process is similar to the "first-party application + resource owner credentials mode"

10.2.3 Third-party web application + authorization code mode

A third-party cooperative manufacturer has developed a Web site to access ACME's e-commerce open platform API. This is a third-party web application scenario, usually using the OAuth 2.0 authorization code permission mode

Let's take a look at the authentication and authorization process. Again, here just highlight the key steps and assume a successful flow

insert image description here

  1. The user visits this third-party web application, clicks the login link
  2. The web application background sends an application authorization code request to ACME's IDP service ( GET /authorize)
  3. User is redirected to the IDP unified login page of ACME Corporation
  4. User authentication and authorization
  5. IDP authenticates users through Login Service
  6. Authentication and authorization pass, and IDP returns an authorization code
  7. The web application obtains the authorization code, and then initiates a request to the token acquisition endpoint of the IDP service ( POST /oauth2/token, grant_type=authorization-code)
  8. IDP verifies the authorization code, and returns a valid OAuth 2.0 token if the verification is passed (it can also return a refresh token as needed)
  9. The web application creates a user session, saves the OAuth 2.0 token in the session, and then returns the login success to the client
  10. The session cookie is recorded in the user's browser, and the login is successful

Later, if the third-party web application needs to interact with the ACME e-commerce platform, it can directly call the microservice through the gateway, and request the OAuth 2.0 access token in the HTTP header. The subsequent service invocation process is similar to the previous "first-party application + resource owner credentials mode"

10.2.4 Additional Notes

1. The API of IDP should support the conversion from OAuth 2.0 access token to JWT token

The integration architecture mentioned above adopts the mixed mode of OAuth 2.0 access token + JWT token, and needs to realize the mutual conversion between OAuth 2.0 access token and JWT token. This interchange API is not a standard of OAuth 2.0, and some IDP products (such as Spring Security OAuth) may not support it, so user-defined extensions are required

2. About single-page SPA application scenarios

Regarding the single-page SPA application scenario, the simple way is to use implicit permission, but this mode is relatively insecure in OAuth 2.0, so it is generally not recommended. For pure single-page SPA applications, the recommended practice in the industry is:

  • If the browser supports Web Crypto for PKCE, you can consider using an authorization code license + PKCE extension process similar to the "first-party mobile application" scenario
  • Otherwise, consider the SPA+traditional Web hybrid (hybrid) mode. The front-end page can be planted in the client browser, but the login authentication is still implemented by the back-end Web site, which is similar to the resource owner credential model of the "first-party Web application" scenario. , or the authorization code licensing mode in the "third-party web application" scenario

3. About the SSO single sign-on scenario

To simplify the description, the above process does not consider the SSO single sign-on scenario. If Web SSO is to be supported, various application scenarios must be logged in through the browser + IDP login page, and the IDP must support Session to maintain the login status. If IDP is deployed in cluster mode, sticky Session or centralized Session should also be considered

In this way, when a user logs in through a web application, if he logs in with other web applications later, as long as the session on the IDP still exists, the login can be completed automatically, which is equivalent to single sign-on

Of course, if you want to support SSO, the session cookie of IDP must be planted on the root domain of the web application, that is to say, the root domains of different web applications must be the same, otherwise there will be cross-domain problems

4. Deployment method of IDP and gateway

In the previous architecture diagrams, although the IDP hides behind the gateway, in fact, the IDP can be directly exposed to the outside through Nginx without going through the gateway. Or, the login authorization page of IDP can be directly exposed through Nginx, and the API interface is through the gateway

5. Refresh token

To simplify the description, the flow above does not detail how refresh tokens are integrated. According to the needs of the scenario, enterprises can enable refresh tokens to extend the user's login time. The specific integration method needs to consider the security requirements

6、Web Session

In order to simplify the description, in the above process, it is assumed that the Web Session is enabled after the Web application login is successful, that is, the server-side Session. In actual scenarios, Web Session is not the only option. You can also use a simple client-side Session method, also known as a stateless session, that is, save the OAuth 2.0 access token in the client browser cookie

10.3 Summary

1. The current mainstream microservice architecture can be roughly divided into 5 layers, namely: Nginx traffic access layer -> Web application layer -> API gateway layer -> BFF aggregation layer -> domain service layer. This architecture can live in a cloud-native Kubernetes environment or in a traditional data center

2. The API gateway is the entry point for microservice calls and undertakes important security authentication and authentication functions. Key security operations include:

  1. Verify OAuth 2.0 access token through IDP and get JWT token with user and permission information
  2. Authenticate API calls based on OAuth 2.0 Scope

3. Under the microservice architecture system, a centralized IDP service is usually required, which is equivalent to an Authentication & Authorization as a Service role, responsible for token issuance/verification/management, and user authentication

4. In the architecture proposed above, the security mechanism of the Web application layer (before the gateway) is mainly implemented based on the OAuth 2.0 access token (it is a transparent token or reference token) , and the security mechanism of the microservice layer (behind the gateway) The security mechanism is mainly implemented based on the JWT token (which is an opaque self-contained token) . The gateway layer implements the conversion of the two tokens in the middle. This is a hybrid of OAuth 2.0 access token + JWT token

The reason for this design is that the web layer is close to the user end. If JWT tokens are used, user information will be exposed, which has certain security risks. Therefore, OAuth 2.0 access tokens are used, which are meaningless random strings. After the gateway, the security risk is relatively low, and many services require user information, so it is more appropriate to use JWT tokens that contain user information

Of course, if the enterprise intranet has no special security considerations, it is also possible to directly transmit completely transparent user information (for example, using JSON format)

11. How do major open platforms use OAuth 2.0?

Earlier, the "open platform" was mentioned many times. It is not difficult to understand that its function is to enable enterprises to empower external developers with their business capabilities mainly in the form of open APIs. As third-party developers or ISVs (Independent Software Vendors), when accessing these open platforms, what we should care most about is their official documents, focusing on what the access process is, what the corresponding API is, and how each Which parameters are passed by each API is almost enough

At this point, you will find that "official documents of the open platform" will be a key point. However, when you look at these documents on major open platforms, you will find that these documents are very scattered

The reason is also very simple, that is, in order to allow R&D personnel who already have OAuth 2.0 knowledge to quickly connect to the business on the platform, the open platform has categorized and archived various docking processes. For example, you will find that there are documents on the WeChat open platform that use authorization codes to obtain authorization information, and documents on obtaining tokens, but there is no overall document description that can be strung together. This actually indirectly raises the threshold of use, because if you don't understand OAuth 2.0, you basically can't understand those classifications

Next, let’s talk about how the major open platforms represented by Jingdong, WeChat, Alipay, and Meituan use OAuth 2.0. After understanding this problem, when you connect to an open platform and read an official docking document in the future, you will be able to understand their underlying logic better.

Before officially introducing the details of the use of the major open platforms, let’s take a look at the overall system of the open platforms of the major manufacturers. The basic system structure of each open platform and the interaction process of the authorization system in the middle are similar, and they are all authorized through the authorization service and authenticated through the gateway. So next, let’s take JD.com’s merchant open platform as an example to see what the open platform system looks like.

11.1 What does the open platform system look like?

First, let’s take a look at the structure of the overall system of the JD Merchant Open Platform, as shown in the figure below:

insert image description here

This architecture can be divided into three parts:

  1. Third-party software: generally refers to the application software implemented by third-party developers or ISVs through docking with open platforms, such as Xiaotu ordering software
  2. JD merchant open platform: including API gateway service, OAuth 2.0 authorization service and third-party software developer center service. Among them, API gateway service and OAuth 2.0 authorization service are the "two legs" of the open platform; third-party software developer center service is to provide developers with services to manage basic information of third-party software applications, such as app_id, app_secret and other information
  3. Various micro-services within JD.com: such as order service, commodity service, etc. These microservices are the previously mentioned protected resource services

It can also be seen from the figure that the overall call relationship of this system is: the third-party software requests to the open platform through the HTTP protocol, more specifically, the API gateway service of the open platform, and then the API gateway calls to each micro server through the internal RPC Serve.

Next, let’s take user Xiaoming’s use of Xiaotu’s billing software as an example to see how these system roles interact with each other.

insert image description here

  1. When user Xiaoming accesses the Xiaotu software, Xiaotu will first request an access token from the OAuth 2.0 authorization service of the open platform, and then Xiaotu takes the access token to request the API gateway service
  2. In the API gateway service, two basic checks will be done, one is the validity check of the access token, such as checking whether the access token is expired, and the other is the basic information of the Xiaotu billing software Validity verification, such as verification of app_id and app_secret
  3. After the verification is successful, the API gateway service will initiate the final data request

What needs to be explained here is that, as mentioned earlier, when verifying the access token or third-party software application information, it is all done in the protected resource service. When there is an API gateway layer, these verification tasks will all fall on the API gateway, because many protected resource services cannot be allowed to do the same thing

Relying on the capabilities provided by the open platform, it can be said that the open platform, users and developers have achieved a win-win situation: Xiaoming has improved the ordering efficiency because of using Xiaotu; The API allows Xiaotu to help Xiaoming to process the orders of C-end users extremely quickly, and JD.com has improved the user experience

But at the same time, openness is also a double-edged sword. Ideally, the platform, developers, and users can achieve a win-win situation, but security issues cannot be ignored, and user information security is the top priority. Next, let's look at a case of how an open platform system solves the security problem of access tokens

After the user authorizes the third-party software, the authorization service will generate an access token, and this access token is associated with the user. For example, if Xiao Ming authorizes the Xiaotu billing software, then the granularity of the access token at this time is: Xiaotu billing software + Xiao Ming

Xiaotu order software can use this access token to access Xiao Ming's data on behalf of Xiaoming; if the access token expires, Xiaotu order software can continue to use the refresh token to access until the refresh token expires

Now the problem is, if Xiao Ming logs out of his account or changes his password, the access token he previously authorized for other third-party software should be invalidated immediately. Otherwise, before the refresh token expires, third-party software can always use the previous access token to request data. this is obviously unreasonable

So in this case, the authorization service will receive the user's logout and password modification messages through MQ (message queue), and then clean up the access token

insert image description here

In fact, the way to solve the access token security problem in this case is not only applicable to open platforms, but also can provide reference for you when building your own OAuth 2.0 authorization architecture in the enterprise

The above is the overall structure of the open platform, and the security issues of user access tokens that need to be focused on. As a third-party software developer, when connecting to these open platforms or browsing their websites, we can almost see a sentence like this: "All interfaces need to be connected to OAuth authorization, and can only be called after the user confirms the authorization. ", which is the fundamental role of OAuth 2.0

11.2 Authorization process of major open platforms

Take WeChat, Alipay, and Meituan as examples to see how they use OAuth 2.0 in open authorization. First, look at the official authorization flow chart:

insert image description here

insert image description here

insert image description here

As you can see in the three authorization flow charts, there are texts related to the authorization code code. This means that they all recommend that developers prefer the authorization code flow

It is also mentioned at the beginning of this section that when a developer connects to an open platform, what he cares most about is the official docking documents they provide. Among these documents, the most troublesome thing is the parameters that need to be passed during the communication process. Next, take the Jingdong Merchant Open Platform as an example to see the meaning behind these parameters and the key points

11.3 Parameter description in the authorization code process

In a nutshell, on the authorization service side of JD Merchant Open Platform, there are two endpoints that provide services: the authorization endpoint responsible for generating authorization codes and the token endpoint responsible for issuing access tokens. Throughout the authorization process, although there are many parameters, you can classify them around these two lines

Next, continue to take Xiaotu ordering software as an example to see what parameters it uses when it connects to the open platform of Jingdong merchants

When Xiaoming was using Xiaotu’s ordering software, Xiaotu was first redirected to the authorization service of JD’s merchant open platform by Xiaotu. In fact, he was directed to the authorization endpoint of the authorization service. The parameters used in this redirection process are as follows:

parameter required describe
response_type yes The code value must be used to indicate the request authorization code permission process
app_id yes The application ID assigned by the developer of the third-party software when registering on the open platform
redirect_uri yes The callback URI that the developer of the third-party software fills in when registering on the open platform. When the authorization service returns the authorization code code, it is sent to this address.
scope optional The requested scope, if not, the authorization service will provide the corresponding permission scope based on the determined policy
state recommend For third-party software to do the most basic protection against CSRF attacks

What needs to be emphasized here is that for the state parameter, it is now officially "recommended". However, the official OAuth 2.0 recommended way to avoid CSRF attacks is to use the state parameter. So to be on the safe side, you should use

Then, the authorization endpoint of JD Merchant’s open platform authorization service will respond to Xiaotu software. The basic parameters used in this response process are as follows:

parameter required describe
code yes Authorization code generated by the authorization server
state yes The state value sent by the third-party software when requested, the authorization service needs to return it to the third-party software as it is

For the value of the authorization code code, the generally recommended maximum lifetime is 10 minutes. In addition, the Xiaotu billing software is only allowed to use the value of the authorization code once. If the same authorization code value is used to request after one use, the authorization service must refuse

For this state value, the authorization service must return to Xiaotu ordering software every time. No matter whether Xiaotu ordering software has sent this value at the beginning, it must return it, and if not, it will return empty. In this way, when Xiaotu’s billing software is upgraded to increase the value in the future, the Jingdong Merchant Open Platform does not need to change any code logic

After getting the value of the authorization code code, the next step is that Xiaotu ordering software initiates a request to the token endpoint of the authorization service of the Jingdong Merchant Open Platform to apply for an access token. The basic parameters that need to be passed in this process are as follows:

parameter required describe
grant_type yes The authorization_code value must be used to indicate the request authorization code permission process
code yes The authorization code code value received by the third-party software from the authorization endpoint of the authorization service
redirect_uri yes The callback URI filled in by the developer of the third-party software when registering on the open platform, the authorization service must verify the value
app_id yes The application ID assigned by the developer of the third-party software when registering on the open platform
app_secret yes The application key assigned by the developer of the third-party software when registering on the open platform

After the authorization service receives the request from the Xiaotu billing software to apply for an access token, like the authorization endpoint, the token endpoint also needs to respond to the Xiaotu billing software. The basic parameters involved in this process are as follows:

parameter required describe
access_token yes The value of the access token issued by Open Platform's authorization service
token_type yes The type of access token, currently the default unified token is bearer type
refresh_token yes A refresh token, which third-party software can use to update the value of a new access token
expires_in yes The validity period of the access token, in seconds
re_expires_in yes The validity period of the refresh token in seconds
scope yes The actual scope of permissions that third-party software is allowed to use

As for the scope value returned here, it needs to be emphasized that it is actually the actual permission scope allowed by Xiaotu software, because Xiaoming may grant Xiaotu software a smaller permission scope than it applied for when registering on the open platform. For example, Xiaotu’s ordering software has applied for the permission to query the historical orders and the current day’s order API, but Xiao Ming may only authorize Xiaotu’s API permission to query the current day’s order

12. Summarize OAuth 2.0 FAQs

1. What is the purpose of inventing OAuth?

The original intention of the design of the OAuth protocol is to allow the end user, the resource owner (Xiao Ming), to entrust some of their permissions (query the order of the day) on the protected resource server (JD Merchant Open Platform) to a third-party application (Xiaotuda single software), enabling the third-party application (Xiaotu) to perform operations on behalf of the end user (Xiaoming) (query the order of the day)

This is what the OAuth protocol was designed for. In the OAuth protocol, credentials with limited access to protected resources, that is, access tokens, are generated for each combination of third-party software and each user to replace the previous username and password. The login operation before the access token is generated is between the user and the platform, and the third-party software has no way of knowing any information about the user.

In this way, the logical processing of third-party software is greatly simplified, and its future actions become requesting access tokens, using access tokens, and accessing protected resources. At the same time, when third-party software calls a large number of APIs, it no longer transmits user usernames and passwords, thereby reducing the attack surface of network security

From a security point of view, generating an access token for each combination of third-party software and each user can reduce the harm caused to more users of the platform. Because in this way, the harm caused by the breach of a single third-party software will only affect the users of this third-party software.

Then you may ask at this time, so that the target of the attack will be transferred to the authorization service. This idea is correct, but it is definitely easier to protect one licensed service than thousands of third-party software developed by different developers

2. Is OAuth 2.0 an identity authentication protocol?

OAuth 2.0 is an authorization protocol, "it's all about doing authorization well", OAuth 2.0 is not an authentication protocol

You may think that there are users involved. For example, Xiaoming needs to log in to the authorization service for identity authentication before using the Xiaotu billing software. Then OAuth 2.0 should be an identity authentication protocol.

However, Xiao Ming must log in to authorize, which is an additional requirement, and the login and authorization systems are independent. Although the login operation seems to be "embedded" in the OAuth 2.0 process, login and authorization are still two independent systems in the production environment. Therefore, such "embedded" identity authentication behavior does not mean that OAuth 2.0 itself assumes the responsibility of the identity authentication protocol

At the same time, identity authentication will tell the third-party software who the current user is, but in fact, OAuth 2.0 has not disclosed any information about the user to the third-party software from beginning to end. This point was also mentioned above when talking about the purpose of inventing the OAuth protocol. You can think about the example of Xiaotu ordering software again to see if this is the case: Xiaotu ordering software will never know any information about Xiao Ming, it just requests an access token, uses the access token and finally calls the query order APIs

3. With the refresh token, can the access token be valid all the time?

First review several knowledge points related to access tokens and refresh tokens:

  1. The core of OAuth 2.0 is authorization, and the core of authorization is the token, which is the so-called access token
  2. In order to improve the user experience, OAuth 2.0 provides a mechanism to refresh the token, so that after the access token expires, third-party software can re-request an access token without the need for the user to authorize again
  3. In use, refresh tokens can only be used on authorized services, and access tokens can only be used on protected resource services

When the access token is "handed" to the protected resource service, the protected resource service needs to verify the access token, and also check the permission matching between the permission associated with the access token and the request of the third-party software. When the access token expires, the access token requested using the refresh token is regenerated by the authorization service instead of extending the validity period of the original access token

After the current refresh token is used, the authorization service can decide whether to issue a new refresh token or return the previous refresh token to the third-party software. To be on the safe side, the recommendation is to return a new refresh token. At this time, there may be a question: the third-party software has changed an access token, and the refresh token still exists, so can the refresh token be used to obtain the access token?

To resolve this doubt, it is important to know that refresh tokens also have an expiration date. Although a new refresh token is generated, its expiry date does not change, and the expiry date's timestamp is still that of the previous refresh token. The validity period of the refresh token has expired, so it can no longer be used to apply for a new access token

4. Can the data security of the JWT format token be guaranteed by using HTTPS?

OAuth 2.0 should never be used without HTTPS. Because sensitive information such as access tokens and application keys must be transmitted over the network, HTTPS protection is inseparable. However, HTTPS only guarantees the security of important information such as access tokens in network transmission

In the OAuth 2.0 specification, access tokens are opaque to third-party software and should never be parsed by any third-party software. Since a token in JWT format self-contains information about the user, such as a user ID, simply signing it is not enough. To prevent third-party software from having the opportunity to obtain the information contained in the access token, when using the token in JWT format in an environment that interacts with third-party software, it must also be encrypted to ensure the security of the token, not just Rely on HTTPS

5. Is there a connection between ID tokens and access tokens?

When implementing an OpenID Connect authentication protocol with OAuth 2.0 in Section 9, we talked about ID tokens. First, let’s summarize the functions of ID tokens and access tokens:

  • ID token, that is, ID_TOKEN, represents the user identity token, which can be said to be a separate identity authentication result, and will never be passed to other external services as a parameter like an access token
  • An access token, also known as ACCESS_TOKEN, is a token that is to be used by third-party software as a credential to request protected resource services on behalf of users

From this it can be seen that the two tokens are distinct

  1. ID tokens are complementary to access tokens, not intended to replace them. The reason why such a double-token method is adopted is to allow the previously existing access token to continue to remain opaque to third-party software in OAuth 2.0, and to allow the newly added ID token to be able to be parsed. It is convenient to apply to the identity authentication protocol
  2. ID tokens and access tokens have different lifetimes, with ID tokens having a relatively shorter lifetime. Because the role of the ID token is to represent a separate identity authentication result, its mission is to identify the user. And this identifier is not the user name. When the user logs in, the user name is used instead of the ID token, so if the user logs out or logs out, the life cycle of the ID token ends
  3. Access tokens can continue to be used by third-party software to request protected resource services long after the user has left. For example, Xiao Ming uses the batch export order function of Xiaotu Ordering Software. If it takes a relatively long time, Xiao Ming does not have to be present all the time

6. What problem does the PKCE protocol solve?

In Section 7, using OAuth2.0 in mobile apps, we talked about the PKCE protocol. Let's first look at the background of its launch

In October 2012, the official authorization protocol framework of OAuth 2.0, namely the official RFC 6749, was officially released. In September 2015, the PKCE protocol was added, which is the official RFC 7636. In terms of time, from the official release of the OAuth 2.0 authorization protocol to the supplementary release of the PKCE protocol, there is a full interval of three years, and these three years are exactly the period when mobile applications are booming.

At the same time, there are special security issues in storing secret keys in native mobile client applications, and clients using OAuth 2.0 authorization code permission types are vulnerable to authorization code eavesdropping attacks

Therefore, the background of PKCE being supplemented and released is that mobile applications are developing vigorously, and at the same time, native clients face security risks when using OAuth 2.0. In this way, we can understand that the purpose of publishing the PKCE protocol is mainly to mitigate attacks against public clients and improve the security of the use of authorization codes.

Guess you like

Origin blog.csdn.net/ACE_U_005A/article/details/128779217