OAuth 2.0 and its vital role in application data security, explained simply (Part 2)
We hope that part one of this blog series gave you a clear overview of OAuth 2.0 and its importance in enforcing security and granular permissions when personal information is shared between apps. Now that you have a handle on the basics, in this blog, we are going to take things up a notch.
As you will no doubt remember, in our previous blog, we used an office access control system analogy to explain the high-level concepts behind the most common OAuth 2.0 flow, Authorisation Code Grant. This time we’ll go through it again using a more realistic example, which we’ll relate back to our analogy.
OAuth 2.0 Authorisation Code Grant: Actors and Concepts
We previously introduced the Birthday Reminders app, which uses your Facebook friends’ dates of birth to remind you to wish them a happy birthday. In this scenario, OAuth 2.0 Authorisation Code Grant allows you to delegate access to a very specific subset of the data in your Facebook account (your friends’ birthdays) to the Birthday Reminders app, without sharing any of your credentials. Before we start, let’s remind ourselves of the different OAuth 2.0 concepts and actors.
ℹ️ In our office analogy, Foo Corp was the Resource Owner.
Although Resource Owners can be corporations, they usually tend to be individuals like you or me. It would not be wrong to say that by extension, the Resource Owner was in fact Mrs Foo, the CEO of Foo Corp. In this example, the Resource Owner is you: while you do not own Facebook, you do “own” your profile data, your posts, your photos and so on.
ℹ️ In our office analogy, Bar Tower was the Resource Server.
This time, it’s Facebook. That’s where the data (or resource) that you control is held. This maps to Bar Tower, which is where Foo Corp (the Resource Owner) has its office. Just like there are other offices in Bar Tower that are not leased by Foo Corp, there are obviously other profiles on Facebook, as well as yours. More specifically, the Resource Server is the actual Facebook API that returns your friends’ birthdays, which is your data that the app wants to access.
ℹ️ In our office analogy, employees were Clients, to whom Foo Corp delegated access to specific floors of the office.
In this scenario, the Birthday Reminders app is our Client. It’s the actor requesting your consent (as the Resource Owner) to access the Facebook API that returns your data (the Resource Server). Only you hold the right to decide whether or not to delegate your access to Birthday Reminders.
ℹ️ In our office analogy, the security desk was the Authorisation Server.
The Authorisation Server orchestrates the OAuth 2.0 flow. It creates the Access Tokens which grant Clients access to the Resource Server. In this case, it’s the Facebook Auth Server. As a Resource Owner, you already have a relationship with the Authorisation Server, for example here you have a Facebook account. The Auth Server asks for your consent to delegate your access to Clients such as Birthday Reminders, and if granted, generates their Tokens. You will only be asked to consent to the specific Scopes that the client has requested.
ℹ️ In our office analogy, keycards represented Access Tokens.
Generated by the Authorisation Server with consent from the Resource Owner, Access Tokens are a Client’s key to retrieving data from the Resource Server. They’re often implemented as JSON Web Tokens (JWT), but can be other types of token. The Token doesn’t store any of the Resource Owner’s credentials. To the Client, it’s nothing more than a meaningless entity that unlocks access to the Resource Server. Facebook will only share your friends’ birthdays with Birthday Reminders when its Resource Server is presented with a valid Token by the app.
ℹ️ In our office analogy, the security desk would code new keycards with a permissions group that would allow employees to go to the specific office floors required to carry out their roles. These permission groups represented OAuth 2.0 Scopes.
While a Token can unlock access to all of the Resource Owner’s data, often only a subset of the data needs is required. Birthday Reminders only need your friends’ birthdays, your photos are not required. This is where Scopes come in. They make it possible to delegate access to discrete portions of the Resource Owner’s data. Clients usually only request access to the Scopes they require to fulfil their purpose, and the Resource Owner has full control over which Scopes are granted. Scopes can encompass one or several APIs.
For reference with our office analogy, here’s the summary table we used last time.
|OAuth 2.0||Foo Corp Analogy||Birthday Reminders|
|Resource Owner||Foo Corp||You|
|Resource Server||Bar Tower|
|Client||Employees||Birthday Reminders App|
|Authorisation Server||Security Desk||Facebook Auth Server|
|Access Token||Key Card||Access Token|
|Scopes & APIs||Office Floors||Profile, Photos, Timeline|
Before OAuth, all we had was Basic Auth
In Part I of this blog series, we saw how before introducing keycards (OAuth2.0), Foo Corp used a simple keypad and secret code to grant employees access to the office. This represented Basic Auth.
Before OAuth 2.0, when Birthday Reminders needed to access your Facebook account to get your friends’ dates of birth, you had to give Birthday Reminders your Facebook username and password. When working with APIs, credentials had to be encoded directly into the API calls. This was Basic Auth, and it’s still used by some apps today.
While Basic Auth is appropriate in some simple scenarios, for example when users are logging into their account on a platform, there are a number of drawbacks when it’s used for access delegation.
Firstly, it’s not very secure, because you are essentially disclosing your username and password with a third-party app. You have to fully trust that Birthday Reminders will keep your credentials safe and won’t share them any further, as you have no way to enforce it. Birthday Reminders might keep passwords unencrypted or could be hacked, resulting in your credentials being compromised. Furthermore, if you ever changed your Facebook password, Birthday Reminders would no longer be able to access your Facebook account and you would miss your friends’ birthdays, which would be very sad.
Secondly, once you’ve shared your credentials with Birthday Reminders, the app has exactly the same level of access to your Facebook account as you have. You have no way of monitoring or enforcing that it will only retrieve your friends’ birthdays, rather than say, your photos.
Lastly, there’s no way for you to track which of your Facebook data Birthday Reminders has been accessed. At best, you could check the login history of your Facebook account and try to work out which events were not yours. But from Facebook’s perspective, it cannot differentiate you from the app, as you’re both using the same credentials.
These are the main drawbacks which are eliminated by OAuth 2.0. In the next section, we’ll take a look at how it lets you delegate access to only the specific parts of your Facebook account that Birthday Reminders actually needs.
The modern way – OAuth 2.0
There are four different “flows” in OAuth 2.0, which are appropriate for different scenarios. Where we need to delegate our access to an app to a less trusted app, like in our Birthday Reminders example, we tend to use the Authorisation Code Grant flow. As it involves three parties (a Resource Owner delegating their Resource Server access to a Client), it’s sometimes referred to as “3-Legged OAuth”, or “3LO”. Let’s take a look at how the flow works with the help of our example.
Everything starts off when you first set up the Birthday Reminders app. It needs to acquire an Access Token in order to use Facebook’s ‘user’ API, so it contacts Facebook’s Authorisation Server. The Auth Server asks for your consent, but first it needs to make sure it’s you, so it will ask you to log in if you don’t already have an active session. With your consent granted, the Auth Server will generate an Access Token that Birthday Reminders can now use to access your data.
However, there is an intermediate step which for simplicity, was not represented in the Foo Corp analogy and the diagram above. This OAuth 2.0 flow’s name actually comes from this step. Once it has your consent, the Auth Server actually sends Birthday Reminders an Authorisation Code, which Birthday Reminders sends straight back to the Auth Server along with its unique Client ID and Client Secret. Only then does the Auth Server generate and send the Access Token.
The Client ID is unique to Birthday Reminders, and the Client Secret is kept strictly confidential between the Client and the Auth Server. Used together, the ID and Secret allow the Auth Server to identify the Client as the Birthday Reminders app, which is important so that it doesn’t just hand out Access Tokens to anyone. It was the Facebook Auth Server which generated Birthday Reminders’ Client ID and Client Secret at the time when Birthday Reminders’ developers set up the app to work with Facebook.
Now when Birthday Reminders wants to retrieve your friends’ dates of birth, it shares its Access Token with the Resource Server, which grants it access to the ‘users’ API. It’s important to note that the Access Token only grants access to this specific API, so Birthday Reminders can’t start accessing your Facebook photos and timeline.
In OAuth 2.0, subsets of your data on the Resource Server that Clients can access are called Scopes (although Facebook calls them Permissions). Scopes could be individual APIs or collections of APIs, usually grouped together when they are related and serve a common purpose. The Scope of the access delegated to Birthday Reminders is Facebook’s ‘users’ API, and that API allows other data to be accessed by the app, such as the friends’ names.
OAuth 2.0’s Authorisation Code Grant flow addresses all of the drawbacks of Basic Auth in scenarios where you want to delegate your access to one app to another. Your credentials are safe as they are never shared with the app you’re delegating access to. Tokens expire and can be revoked, so even if a Token is stolen, the damage can be mitigated. Access to your data is enforced by the system rather than based on trust. And finally, the system enables a finer granularity of audit, as it records when specific data was accessed rather than just an account login event.
In this two-part blog series on OAuth 2.0, we’ve been discussing Authorisation, the mechanism that enables access delegation. This is not to be confused with Authentication, which is what the Authorisation Server does to verify your credentials and log you in. OAuth 2.0 is often used in conjunction with OpenID Connect (OIDC), which extends the authority of OAuth 2.0 to introduce the element of Identity. Services such as “Sign in with Google” are using OAuth 2.0 and OIDC to allow you to log into Client applications with a pre-existing account created on another platform (e.g. Google). Clients use OIDC to retrieve information about you, the Resource Owner, from the Authorisation Server.
While OAuth 2.0 is widely adopted in the app world, e.g. apps like Birthday Reminders, it’s less prevalent in app integration platforms and solutions. Typically, these allow you to create integrations that rely on Basic Auth to act on your behalf.
Here at Adaptavist, we recognise the importance of securely implementing access delegation and we’ve been thinking of ways to address this problem in the Atlassian space and beyond. Many of our tools already harness the benefits of OAuth 2.0. For example, you can safely delegate your Jira access to our SearchMy app to let it pull issues from your multiple Jira instances into Slack.
However, these tools serve a single purpose. We’re now working on a next generation of open-ended tools to let developers create custom Atlassian apps and integrations that support seamless identity mapping between different platforms and services, significantly facilitating multi-instance operations such as migrations. Keep an eye out across our channels for more news in the near future.