06 Besides Authorization Code Grant Type, What Other Authorization Flows Does Oauth 2.0 Support

06 Besides Authorization Code Grant Type, What Other Authorization Flows Does OAuth 2 #

Hello, I am Wang Xindong.

When studying the principles and workflows of the authorization code grant type in the previous lectures, I don’t know if you have had such a question: Is the authorization code grant flow the most complete and secure, but is it suitable for all authorization scenarios? In some scenarios, is it too complex or unnecessary to use the authorization code grant?

For example, Xiao Tu’s order printing software is officially developed by JD.com. So when Xiao Ming uses Xiao Tu, does he still need to go through the authorization code grant flow again? I guess you can already guess the answer, which is definitely not necessary.

Do you still remember the characteristics of the authorization code grant flow? It allows users like Xiao Ming to participate by using an authorization code as a temporary intermediate value, which establishes a connection between Xiao Tu’s software and JD.com, and allows Xiao Tu to access Xiao Ming’s order data on JD.com’s store on behalf of Xiao Ming.

Now Xiao Tu has been “absorbed” and is own by JD.com. Xiao Tu is now fully trusted by JD.com, and there is no need for the concept of “third-party software” anymore. At the same time, Xiao Ming is also a merchant in JD.com’s store, which means that both the software and the user are assets of JD.com. In this case, it is obviously unnecessary to use the authorization code grant type for authorization anymore. However, Xiao Tu still needs to access the order data Web API through the internet to provide the function of order printing for Xiao Ming.

Therefore, in order to protect these scenarios’ Web API and make OAuth 2.0 better adapt to more real-world scenarios, such as the aforementioned Xiao Tu software, the OAuth 2.0 system also provides the resource owner password credentials grant type.

Resource Owner Password Credentials Grant #

From the name “Resource Owner Password Credentials Grant”, you can probably already understand its meaning. Yes, the credentials of the resource owner are the user’s credentials, namely the username and password. As you can see, this is the worst way to do it. So why does OAuth 2.0 still support this type of grant, and why is it included in the OAuth 2.0 specification?

Let’s think about it for a moment. As I mentioned earlier, Xiaotu is a software produced by JD.com, and Xiaoming is also a user of JD.com. So Xiaoming can actually use his username and password to directly use Xiaotu. The reason is simple: there is no longer a concept of “third party” here.

However, if Xiaotu uses Xiaoming’s username and password to access Xiaoming’s store order data, and even the product information, by calling Web APIs every time, it undoubtedly increases the attack surface of sensitive information such as usernames and passwords.

If a token is used to replace these “flying around” sensitive information, can’t it largely protect sensitive information? In this way, Xiaotu software only needs to use the username and password data once to exchange for a token, and then use the token to access Xiaoming’s store data, without using the username and password anymore.

Next, let’s take a look at the flow of this grant type, as shown in the following diagram:

Resource Owner Password Credentials Grant Flow

Figure 1. Resource Owner Password Credentials Grant Flow

Step 1: When the user accesses the third-party software Xiaotu, they will be prompted to enter their username and password. Requesting the username and password is the characteristic of the Resource Owner Password Credentials Grant type.

Step 2: The value of grant_type here is password. It tells the authorization server to request access using the resource owner password 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));

Step 3: After verifying the username and password, the authorization server generates an access_token value 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");
    response.getWriter().write(accessToken);
}

At this point, you can understand one piece of information: if the software is an official product and you want to use OAuth 2.0 to protect your Web APIs, you can use the approach of Xiaotu software, which is the Resource Owner Password Credentials Grant type.

Whether it is our architecture, system, or framework, it is dedicated to solving various problems in real-world production. In addition to the Resource Owner Password Credentials Grant type, the OAuth 2.0 framework also provides the Client Credentials Grant and Implicit Grant types to address the realities of the environment. Next, let’s continue to look at these two authorization grant types.

Client Credentials Grant #

When there is no specific resource owner involved, in other words, XTRabbit software accesses data that does not require user Xiao Ming’s authorization, such as obtaining the image address of Jingdong’s logo, this logo information does not belong to any third-party user. For example, other types of third-party software accessing the province information provided by the platform, which also does not belong to any third-party user.

In this case, the role of the resource owner is no longer required in the authorization process. Of course, you can also understand it as “the resource owner is embedded in the third-party software” or “the third-party software is the resource owner”. In this scenario, the authorization is client credentials grant, and the third-party software can directly use the app_id and app_secret registered to exchange for the value of the access token.

Let’s take Xiao Ming using XTRabbit software as an example to see the entire authorization process of the client credentials grant, as shown in the following figure:

Figure 2: Client Credentials Grant Authorization Process

Another point is that because the authorization process no longer involves the resource owner Xiao Ming, the backend service of XTRabbit software can initiate the request for the access_token at any time, so this type of authorization does not require refreshing the token.

In this way, the key process of the client credentials grant type can be summarized in the following two steps.

Step 1: The third-party software XTRabbit sends a request to the authorization service through the backend service. Here, the value of grant_type is client_credentials, and it informs the authorization service to request access using the credentials of the third-party software.

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));

Step 2: After verifying the legality of app_id and app_secret, generate the value of access_token and return it.

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");
    response.getWriter().write(accessToken);
}

So far, let’s summarize again. When obtaining data that does not belong to any third-party user, there is no need for user involvement like Xiao Ming. At this time, the client credentials grant type can be used.

Next, let’s take a look at the last type of authorization grant we will discuss today, which is the implicit grant type.

Implicit Grant #

Let’s imagine again, what if Xiao Ming’s Rabbit Delivery software application does not have a backend service and is run entirely in the browser, such as a pure JavaScript application. How should OAuth 2.0 be used in this case?

In fact, in this situation, the authorization flow can use the Implicit Grant flow, which can be understood as directly embedding the third-party software Rabbit into the browser.

In this case, Rabbit software doesn’t have any confidential data to hide from the browser, and it no longer needs the value of the application secret app_secret or exchanging the authorization code code for the access token access_token. One of the purposes of using the authorization code is to isolate the information of the browser and the third-party software, ensuring that the browser cannot see the most important access token access_token of the third-party software.

Therefore, the security of the Implicit Grant authorization flow will be greatly reduced. In the authorization flow, the serverless Rabbit software is embedded in the browser, and the process of accessing the browser is equivalent to accessing the entire Rabbit software. Therefore, I use a dashed box to represent the Rabbit software. The entire authorization flow is shown in the following diagram:

Figure 3: Implicit Grant authorization flow

Next, I will use a Get request in Servlet to simulate this flow and show you the related sample code.

Step 1: The user accesses the third-party software Rabbit through the browser. At this time, the third-party software Rabbit is actually an application executed embedded in the browser.

Step 2: This flow is similar to the authorization code flow, with one special point to note: the value of response_type is changed to “token”, which is to inform the authorization server to directly return the value of the access token. As we’ll see later, the Implicit Grant flow is the only flow that requires the return of the access token in the front-end communication. Yes, it’s “bold”, but “insecure”.

Map<String, String> params = new HashMap<String, String>();
params.put("response_type", "token");
params.put("redirect_uri", "http://localhost:8080/AppServlet-ch02");
params.put("app_id", "APPIDTEST");
String toOauthUrl = URLParamsUtil.appendParams(oauthUrl, params);
response.sendRedirect(toOauthUrl);

Step 3: Generate the value of the access token and return it to the third-party software Rabbit 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)) {
    String accessToken = generateAccessToken(appId, "USERTEST");
    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);
}

If your software is directly embedded and running in the browser, without any involvement of the server, and you want to use the OAuth 2.0 flow, just like the example I mentioned above with Rabbit, then you can directly use the Implicit Grant type.

How to Choose? #

Now that we understand the principles and processes of the 4 types of OAuth 2.0 authorization grants, how do we choose which one to use?

Here is my suggestion: when integrating with OAuth 2.0, first consider the authorization code grant type, and then combine it with the real production environment to make a decision:

If Little Rabbit Software is an official product, then the resource owner credentials grant can be used directly;

If Little Rabbit Software is just an application embedded in the browser without a server, then the implicit grant type is the only option;

If the information obtained by Little Rabbit Software does not belong to any third-party user, then the client credentials grant type can be used directly.

Summary #

Okay, we are about to end this article. Before that, we have been talking about the authorization code grant type. You already know that this is the most comprehensive and secure authorization process. However, in the real world, there are always various changes, and OAuth 2.0 also needs to adapt to these changes. That’s why we have discussed three other grant types today. At the same time, I also gave you a suggestion on how to choose and use these grant types.

Including the authorization code grant type we discussed earlier, we have talked about a total of four grant types. The most significant difference between them is the method of obtaining the access token. Finally, let’s compare them using the following table:

Figure 4 Comparison of the 4 OAuth 2.0 grant types

In addition to the differences shown in the table above, I hope you can also remember the following two points.

Among all the grant types, the authorization code grant type has the highest level of security. Therefore, as long as we meet the requirements for using the authorization code grant type, we should always choose it first.

All the grant types are designed to solve practical problems in the real world. Therefore, we should also consider the production environment and choose the most suitable grant type on the premise of ensuring security. For example, the Small Rabbit software using the client credentials grant type is a case in point.

I have uploaded the code we used today to GitHub. You can click this link to view.

Thought Question #

If we are limited by the environment in which the application features are located, such as in a scenario without a browser involved, how should we choose the type of authorization license? Can we still use the authorization code flow?

Feel free to share your thoughts in the comment section. You are also welcome to share today’s content with other friends so that we can exchange ideas together.