Explaining RFC 6749: The OAuth 2.0 Authorization Framework (Part 1)

If you are not familiar with the use cases that prompted a protocol like OAuth 2.0 (often referred to as OAuth2) specified in RFC 6749, understanding the specification will take its toll. When I first started working on OAuth2, it took multiple readings, discussions and help from my peers to make sense of it all. In this essay, I attempt to explain the RFC by walking through real-world examples, which is how I generally retain information. If you are also trying to understand OAuth2, I hope you will find this approach useful, too.

Let’s start with an example of a health application that a user installs from the app store. This application has a social feature which enables groups of friends to participate in various health activities and games. The application developer wants to integrate the application with Facebook to get users’ personal information, such as their name and date of birth, and their friend list.

The question is, why should the application be allowed to access the user’s movie list or status? And once allowed, how long will it continue to have access?

RFC 6749 titled “The OAuth 2.0 Authorization Framework” addresses these issues so that an application can get access to a user’s data with their permission.

Definitions

RFC 6749 defines a few roles in section 1.1. I explain all but one below and will use them off and on in this essay and in subsequent essays. This will make it easier to understand RFC 6749 over time with its specialized terminology.

Client: An application is called a client regardless of whether it’s a mobile application, a desktop application or a web application. It is also referred to as third-party application in RFC 6749’s abstract. In our example, the health application running on a user’s mobile is the client.

Resources: Any data that belongs to the user that the client is trying to access would be a “resource.” For example, the user’s date of birth, name and friend in Facebook would all be resources in this context. In the context of OneDrive or Dropbox, a user’s files would also classify as resources. This term is not explicitly defined in section 1.1 of the RFC but I include it here for clarity.

Resource owner: Date of birth, name and friend list are pieces of data that belong to the user who is referred to as the resource owner. These resources will be shared with the client after the resource owner (i.e., the user) consents.

Resource server: The service that hosts the resources (e.g., Facebook Graph) is called the resource server. This does not refer necessarily to a single server and is referred to as HTTP service in RFC 6749’s abstract. On the web, it is often easier to think of the resource server as a collection of APIs that provides access to the resources.

To summarize, we have a client (an application) that wants to access resources (e.g., name, date of birth, friend list) that belong to a resource owner (the user).

One way to achieve this is for the client to request credentials from the user and send them to the resource server, or send some derivative as proof. The resource server validates the credentials and lets the application access the resources. Section 1 of the RFC addresses issues with this approach.

Shortcomings of “Traditional Client-Server Authentication Model”

Section 1 (Introduction) of RFC 6749 talks about “traditional client-server authentication model” in which the client sends the username and password in request to the server to access resources. This is how basic authentication works, for example, and is shown in Figure 1 below.

Figure 1: In basic authentication, a user provides password to every application which sends it to the server to access resources.

Here are some problems and limitations of such an approach.

Third-party applications are required to store the resource owner’s credentials for future use, typically a password in clear-text.

Let’s say that our health application was coded to use basic authentication. This would mean that the application will prompt the resource owner to provide their username and password to the application. It will then send that username and password to the resource server (e.g., Facebook Graph) to access the user’s data. Either the application will have to ask the resource owner for their credentials every time it starts, which makes for practically an unacceptable experience, or it will store the credentials locally so it can access the resources whenever needed. The client now has perpetual access to the user’s credentials.

Servers are required to support password authentication, despite the security weaknesses inherent in passwords.

To accommodate the scenario described above, an API such as Facebook Graph will need to accept passwords in the requests. Every application that the user downloads requests a username and password. Since Facebook Graph only gets a username and password in every request, it cannot distinguish between different applications or even know how many applications are accessing a user’s data.

Third-party applications gain overly broad access to the resource owner’s protected resources, leaving resource owners without any ability to restrict duration or access to a limited subset of resources.

Since Facebook Graph cannot distinguish between various applications, and provides access based on username and password, all applications get the same access. This is because Facebook Graph would have to expose almost all the resources that Facebook’s own mobile application needs. So, our health application and Facebook’s mobile application appear the same to Facebook Graph because they use username and password to authenticate and, therefore, get same access.

Resource owners cannot revoke access to an individual third party without revoking access to all third parties, and must do so by changing the third party’s password.

This is a corollary of the previous point. In basic authentication model, because a resource server (such as Facebook Graph) cannot distinguish between various client applications, it cannot provide a mechanism for a resource owner to cancel access to any one application. The resource owner must change their password even to deny access to a single application and then provide the new password to every application other than the one they wanted to deny access to their resources.

Compromise of any third-party application results in compromise of the end-user’s password and all of the data protected by that password.

Since every application stores credentials, a compromise of any one of them means that the user’s password (and entire account) is now at the mercy of some malicious user. Anyone with the password can change the password and lock the user out of their own account!

A major shortcoming of basic authentication not mentioned in the RFC is its inability to introduce additional authentication challenges to determine the user’s identity. For example, if Facebook decided to add multi-factor authentication, it cannot easily do so since Facebook Graph is setup based on username and password. Even if Facebook decided that the client applications must do an MFA challenge, how would it determine that the application actually performed that challenge? What additional information can the application pass to Facebook Graph to prove that the user has passed such a challenge?

Authorization Server

To address these issues, OAuth2 framework adds an authorization server in between. The user interacts with authorization server to prove their identity and determine what access the application should get. This means that Facebook Graph must not support password-based access at all; otherwise, applications will attempt to get the password. Facebook Graph must instead use some other credential or it will not know what access to give to which client.

Therefore, every client, such as our health application, is required to identify itself and which resources it wants to access when it redirects the resource owner to the authorization server. Facebook calls its authorization server Facebook Login. The authorization server asks the resource owner which permissions to grant. Then the authorization server creates and issues a new credential to the client application (we will go into the details of the credential in a later essay). This credential is created in a way that the resource server, i.e. Facebook Graph, can validate it was legitimately issued by the authorization server, i.e. Facebook Login. The credential also contains details of what the client, i.e. health application, can access. This allows the resource server to only allow those operations that are permitted to the client. This is shown in figure 2 on the following page.

Figure 2: In OAuth 2.0, a user provides password to authorization server which gives another credential to the client. Client sends that credential to the server to access resources.

The concept of authorization server is not new to OAuth 2.0. SAML identity providers played a similar role, and Active Directory Federation Services (ADFS) is an example of an authorization server that relied on SAML.

Authorization server is the fourth role defined in section 1.1 of the RFC.

Authorization server: The service responsible for confirming a resource owner’s identity and getting their approval (aka consent) to share their resources with the client. Upon approval, the authorization server issues a credential to the client that it can use to gain access to the resources from the resource server.

In other words, the authorization server is authorizing the client to access the resources on behalf of the resource owner. That’s why OAuth2 is called an “authorization framework”.

How does the authorization server establish the identity of the user so it can determine which resources belong to them? This is when the authorization server will challenge the user to provide a password, perform multi-factor authentication, or use other mechanisms to determine their identity. A malicious user should not be able to declare the identity of any other user and gain access to their resources.

After the user has authenticated, they may still decline access to the client for all the resources that the client requested access to. In such a case, the client is still not authorized to access the resources.

How does the authorization server decide which of the user’s resources can the client access? After the user has authenticated, the authorization server informs them of which resources the client is requesting access to. The user, by virtue of being the resource owner, can then either grant or deny access. In some implementations, the resource owner can also select which resources they are willing to share with the client. For example, they may consent to sharing their name and friend list but deny access to date of birth. This process is also called approval interaction. Facebook’s such interaction is shown in Image 1 below.

Image 1: Facebook Login prompts the user to approve permissions for an application.

Given the terminology presented so far, now read the abstract of RFC 6749: “The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.” (emphasis mine).

I will cover the second part about application obtaining “access on its own behalf” in a later essay.

With this, I end the first part of this series. We have covered until section 1.1 of RFC 6749.