Before we learn about OAuth 2.0, it is important that we understand the need for an authorization protocol like OAuth 2.0, and the context in which it will be helpful.
Imagine that you want to start playing a multiplayer game online. You create an account for yourself. The game offers to see if any of your Facebook friends are playing the same game and if so, to help you connect with them. The game needs to access your Facebook account to get your friend list. Now, the million-dollar question: How do you grant the game access to your Facebook account?
The old method
One simple way of doing this is to give your username and password to the account, let it log into your Facebook account and access your friend list. But is it safe? Definitely no. This game could very well be a rogue app that harvests people’s usernames and passwords for various nefarious purposes.
To address this issue, service providers (like Facebook) came up with the ploy of issuing app passwords. You could generate an app password specifically for your game and provide this app password instead of your actual password to grant the game access to your Facebook account.
This solved the following issues: First, you could revoke the game’s access to your Facebook account by removing this app password from your profile instead of having to reset your actual password. Second, you may be using the same password with several accounts and by providing this app password, you ensure that the game can’t use the same password to log into other accounts of yours.
App passwords had their shortcomings too
However, there were still many problems app passwords couldn’t solve. For starters, the game would still have complete access to your Facebook account. Here, in our example, we want the game to access only our friend list. But by allowing the game to log into our account, we grant the game complete access to our account.
The game can do anything with our account. It can post on behalf of us, send messages to our friends, see our personal and sensitive details, and whatnot. We can’t control what the game can do with our account.
OAuth 2.0 was engineered to solve this exact problem. OAuth 2.0 allows us to authorize external apps, such as this particular game in our example, to access only certain parts of our account, or more precisely, only the data we authorize it to access.
The OAuth 2.0 authorization framework
Before we dwell on OAuth 2.0, it will be beneficial to learn about the parties involved in the framework.
- The resource—anything that is of interest to a user or a client (such as the Facebook friend list in our example)
- The resource server—the server that hosts the resource (such as the Facebook server in our example)
- The resource owner—any entity that owns the resource (such as us, a Facebook user, in our example)
- The client—any external party that wants to access the resource owned by us (such as the multiplayer game in our example)
- The authorization server—the server that grants access to the protected resource (we will discuss this in more detail in a while)
Now, we need a mechanism by which we can let our game access our Facebook friend list:
- without having to provide our Facebook username and password to the game
- with the ability to revoke the game’s access to our Facebook account whenever we want to
- and with the means to allow the game to access only the friend list and nothing else
How does OAuth 2.0 work?
Let’s see how OAuth 2.0 helps us achieve the above objectives of ours.
First, there would be a button on the game’s user interface called, for example, “find your Facebook friends”. Once you click on it, you would be redirected to Facebook’s login page should you not already be logged in. You would be entering your username and password to log into your Facebook account. Remember, here you are directly logging in through Facebook instead of providing your credentials to the game.
Next, Facebook would ask if you would like to grant the concerned game access to your friend list. If you say yes, you will be redirected back to your game, and the game would have been granted something called an access token, which it can use to access only your Facebook friend list.
How does the game obtain an access token in OAuth 2.0?
To access protected resources, clients need to show their access tokens to the resource servers to prove that the resource owner has authorized them to access their protected resources.
There are various ways by which this access token can be obtained. These ways or flows are called grant types. There are six different grant types.
- Authorization code
- Implicit grant
- Client credentials
- Device code
- Refresh token
Authorization Code in OAuth 2.0
This grant type is by far the most secure of all grant types.
In this flow, the client application (the game in our example) must have registered themselves with the authorization server (Facebook in our example) to be able to access the protected resource (the friend list). When the client is registered, the client is given an ID and a secret key by the authorization server.
The user interacts with the client through a user agent, which often is a web browser. The client application (the game) runs in a server and we access that server through our browser.
The client application would generate a URL, which would be pointing to the authorization server) with the client ID and a redirect URL appended to it as query parameters. This URL would be linked to a button. In addition, this URL would also have query parameters specifying the resources that the client would like to access and the type of the code, which in this case is the authorization code.
Receiving an authorization code
When the user loads this client application in their browser and clicks on the button, the user will be taken to the authorization server’s endpoint.
If the user is not logged in, they will be asked to log in before proceeding with the rest of the flow. If the user is logged in, the authorization server would ask the user if they approve allowing the client application (the game) to access the restricted resource (Facebook friend list). If the user responds in the affirmative, then the authorization server redirects the user to the redirect URL that was sent appended to the URL to the authorization endpoint. An authorization code will be sent as a query parameter along with this redirect URL.
During the redirect, the user’s browser sends a request to the endpoint pointed by the redirect URL, which would belong to the client application. When the browser sends this request, the client application would obtain the authorization code.
Receiving an access token
Then, the client application running on a server sends a request to the authorization server’s token endpoint with the authorization code, client ID, and client secret to obtain an access token. The client application would now be able to access the protected resource using this access token.
Additionally, along with the access token, the authorization server also sends a refresh token. This token can be used to renew the access token once it expires.
Implicit Grant in OAuth 2.0
This flow is an unsecure one and should not be used unless it is absolutely necessary. Here, the client application generates a URL pointing to the authorization server with the code type set to “token”. When the user clicks on the button, the browser takes the user to the authorization server and the user approves the client application to permit access to their protected resources.
But instead of returning the authorization code, the authorization server appends the access token itself as a URL fragment to the redirect URL.
In the authorization code grant type, since the client ID and the secret are stored in the server, they are not visible to the users. But unlike the access token returned during this flow, in the implicit grant, the access token is short-lived, and a refresh token is not returned.
Why URL fragment?
The access token is returned to the user agent in a URL fragment because the URL fragments are not sent to the server. When the authorization server redirects the user to the redirect URL, the browser would send a request to the client application. Should the access token be sent as a query parameter, then the access token would be sent to the client along with the request. Since most sites don’t use TLS (https), this access token can easily be eavesdropped on during the request by devices in the middle.
In this grant type, applications exchange the username and password directly for an access token. First-party clients use this grant.
This flow is used by clients to access resources belonging to them rather than to access users’ resources. Here, the client ID and secret key are exchanged for an access token.
This flow is used by devices that lack proper input devices. First, these devices send a request to the authorization server to get a device code. Then, this device code is shown to the user along with the URL to authorize the device.
Then, the user visits the URL, authenticates themselves, enters the device code and authorizes the device to access their protected resource.
Next, the device polls the server with the device code to see if the user has authorized it. Once the user authorizes it, it will receive an access token.
This grant type is used to get a new access token after an access token expires. The refresh token is exchanged for a new access token.