07 How to Use Oauth 2.0 in Mobile Apps

07 How to Use OAuth 2 #

Hello, I’m Wang Xindong.

In the previous lectures, I explained OAuth 2.0 based on the scenario of web applications. Besides web applications, there are also a large number of mobile apps in real-world environments. So, can OAuth 2.0 be used in mobile apps, and how can we use OAuth 2.0 in mobile apps?

Indeed, the original application scenario of OAuth 2.0 is web applications. But its greatness lies in the fact that it positions its core protocol as a framework rather than a single protocol. The benefit of this approach is that we can build extensions based on this basic framework protocol in specific areas.

Therefore, in desktop or mobile scenarios, the protocol of OAuth 2.0 can still apply. Considering that the authorization code grant type is the most comprehensive and secure type of grant, when explaining how to use OAuth 2.0 in mobile apps, I will still use the authorization code grant as an example. After all, “if you want to use it, use the best.”

When we develop a mobile app, we can choose a “pure app” architecture without a server-side, such as an app that does not need to communicate with its own server or can call other open HTTP interfaces. Of course, we can also choose an architecture with a server-side, such as an app that wants to record the user’s operation log and save it to the server-side database.

In summary, mobile apps can be divided into two categories: apps without a server-side and apps with a server-side.

图1 两类移动App

Figure 1 Two types of mobile apps

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

If there is a server-side, it is recommended to interact with the authorization service through the server-side to exchange for an access token.

If there is no server-side, the interaction with the authorization service can only be done through front-end communication, such as the implicit grant type mentioned in the previous lecture. Of course, the security of this approach is greatly reduced.

Sometimes, we may think that developing an app does not require a server-side. Well, let’s first take a look at how an app without a server-side can use the authorization code grant type.

App Without Server Side #

In a pure app application without server-side support, our first consideration is how to enable requests and responses to flow freely, just like a web service.

You might think, can I embed a “mini” web server into the app, so that I can use OAuth 2.0 like a web application? Indeed, this is feasible and some apps have already done it.

Such an app can communicate with other web applications by listening to a web server URI running on localhost, just like a regular web application. However, this is not the focus of our discussion this time. If you want to learn more, you can search for more information. With this approach, the app_secret required for requesting an access token can only be stored on the user’s local device, which is not recommended.

At this point, you should guess that the key to the problem lies in how to store the app_secret, because the app will be installed on thousands of terminals, and once the app_secret is cracked, it will have catastrophic consequences. Some students may come up with the idea that if we don’t use app_secret, can’t we exchange for an access token by using the authorization code in the authorization code flow?

Indeed, it is possible, but new problems arise. In the authorization code grant type flow, if the app_secret protection layer is removed, only the authorization code code is left to fight the battle alone. In this case, if the authorization code is stolen, it will cause serious security issues. So, if I don’t use the app_secret and still want to prevent the authorization code from being stolen, is there a good solution?

Yes, OAuth 2.0 provides guidance in this regard. This method is called the Proof Key for Code Exchange by OAuth Public Clients (PKCE) protocol, which we are going to introduce.

In the flowchart below, to highlight the communication process between the third-party software using the PKCE protocol and the authorization service, I have omitted the roles of the protected resource service and the resource owner:

Flowchart Using PKCE Protocol

Figure 2. Flowchart Using PKCE Protocol

Let me analyze the key points of this process.

First, the app itself generates a random string called code_verifier, with a length between 43 and 128 characters. Then, we use this code_verifier to generate a parameter called a “challenge” with the name code_challenge.

So how do we generate the value of this code_challenge? The OAuth 2.0 specification provides two methods, determined by the value of the code_challenge_method parameter:

  • If code_challenge_method=plain, the value of code_verifier is the value of code_challenge.
  • If code_challenge_method=S256, we need to encode the value of code_verifier in ASCII, hash it, and then perform BASE64-URL encoding on the hash value, as shown in the code example below.
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

Now, I know that there are these two values and how they are generated, but what is their relationship with the authorization code flow and how do we utilize them? Don’t worry, let’s continue.

The authorization code flow consists of two steps: the first step is to obtain the authorization code code, and the second step is to obtain the access token access_token using the app_id+app_secret+code. Earlier, we imagined not using the app_secret but still ensuring the security of the authorization code flow, right?

Exactly. The code_verifier and code_challenge parameters are here to help us achieve this “dream”.

In the first step of obtaining the authorization code, we use the code_challenge parameter. It is important to note that we also need to pass the code_challenge_method parameter, so that the authorization service knows the method used to generate the value of code_challenge (either plain or S256).

https:
response_type=code&
app_id=APP_ID&
redirect_uri=REDIRECT_URI&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256

In the second step of obtaining the access token, we use the code_verifier parameter. The authorization service will perform a calculation on the value of code_verifier. How is it calculated? It is the same as the method described earlier when code_challenge_method=S256.

That’s right, in the first step of requesting the authorization code, we have already informed the authorization service about the method used to generate the code_challenge value. Therefore, during the second step, the authorization service compares the calculated value with the value received in the first step. If they match, it issues the access token.

POST https:
grant_type=authorization_code&
code=AUTH_CODE_HERE&
redirect_uri=REDIRECT_URI&
app_id=APP_ID&
code_verifier=CODE_VERIFIER

Now you know how we use the code_verifier and code_challenge parameters. To summarize, we use the value of the code_challenge parameter when exchanging for the authorization code, and we use the value of the code_verifier parameter when exchanging for the access token. Now, some students may continue to ask, why do we do this?

Now, let me analyze it for you.

Our wish is that even without a server-side app, we can still use the authorization code grant flow, right? We can’t use app_secret because it can only be stored on users’ devices, and we are worried about it being leaked.

So, even in the absence of the app_secret protection layer, even if our authorization code code is intercepted, along with the code_challenge, there is no way to reverse-engineer the value of the code_verifier from the code_challenge. However, in the second step of exchanging for an access token, the authorization service needs the value of code_verifier. Therefore, this avoids the security issue of accessing tokens being maliciously obtained.

Now, with the help of the PKCE protocol, we can safely use the authorization code grant type for apps without a server-side. However, according to the recommendations of the OAuth 2.0 specification, using backend communication to exchange for access tokens is a more secure approach. So, here, I would like to discuss with you: do we really not need a server-side? When developing mobile applications, have we really decided to abandon the server-side from a design perspective?

App with Server-side Support #

If you have developed an app integrated with WeChat login, you will see the following sentence in WeChat’s official documentation:

WeChat OAuth 2.0 authorization login currently supports the authorization_code mode, which is suitable for apps with server-side support.

That’s right, WeChat’s OAuth 2.0 authorization login suggests that we need a server-side app to support this type of authorization integration.

So, how does an app with server-side support use the OAuth 2.0 authorization code grant flow? In fact, based on what we have learned in the previous lessons, understanding such a scenario is not difficult.

Figure 3 WeChat login process diagram

When you see this diagram, do you feel familiar? It is similar to the regular authorization code flow, still a two-step strategy: the first step is to exchange for the authorization code code, and the second step is to exchange for the access token with the authorization code code.

The third-party app mentioned here refers to the app we develop, which includes the mobile app and the server-side. Let’s “zoom in” on this diagram:

Figure 4 Authorization process for an app with server-side support

From this “zoomed-in” diagram, we can see that an app with server-side support using the authorization code flow is almost identical to a regular web application.

The general process is as follows: when we access the third-party app, we need to use WeChat to log in; the third-party app can trigger the WeChat app, and we will log in and authorize within the WeChat app; after successful verification by the WeChat server, it returns an authorization code code and passes it to the third-party app through WeChat app; the subsequent process is familiar to us, using the authorization code code and app_secret to exchange for the access token value.

When using app_secret this time, we are using it on the server-side of the third-party app, so there is no security issue.

Summary #

In today’s lecture, I focused on two topics: how to use the authorization code grant type without a server-side app, and how to use it with a server-side app. I hope you can remember the following two points.

The purpose of using the OAuth 2.0 protocol is to enhance security. However, sometimes improper usage can result in even greater security issues, such as the basic mistake of including the app secret in the app itself. So how can we ensure the security of using the authorization code grant type without a server-side app? To address this situation, I introduced the PKCE protocol, which is a solution to prevent theft of the authorization code when the app secret is no longer protected.

We need to consider whether our app really doesn’t need a server-side component. I recommend that when developing a mobile app, you should try to establish a server-side component whenever possible, as transmitting access tokens through backend communication is much more secure than transmitting them through frontend communication. I also mentioned the example of WeChat, where many official open platforms recommend developers to have a corresponding server-side component when providing OAuth 2.0 services.

So, what other security measures regarding the use of OAuth 2.0 should we pay attention to? We will focus on introducing them in the next lecture.

Thought Questions #

In a mobile app, can you think of any relatively secure ways to use OAuth 2.0?

Feel free to share your thoughts in the comments and also share today’s content with other friends. Let’s exchange ideas together.