What is OAuth 2.0 and what does it mean?Link to this section
OAuth (also known as open authorization) is an open-standard authorization framework that has been around since 2010. Its latest iteration is OAuth 2.0, allowing third-party apps to securely access a user’s accounts on a HTTPS service through a process of delegated authorization.
By delegating user authorization to the platform that hosts a user’s account, third-party apps are able to unlock limited access to that user’s account for a range of uses.
With OAuth 2.0, developers can tap into a range of authorization flows that work across web, mobile and desktop apps (along with APIs, devices, services and more).
OAuth 1.0 vs OAuth 2.0Link to this section
It’s important to call out that there are two versions of this protocol that you need to know about: OAuth 1.0 and OAuth 2.0. Importantly, these two versions aren’t compatible.
As you’d expected OAuth 1.0 is the earlier version and has been superseded by OAuth 2.0. That’s due to limited flows and complicated cryptographic demands making it hard to scale the original version.
OAuth 2.0 offers six flows for a range of apps and situations while enabling signed secrets over HTTPS. This version also encrypts tokens in transit (meaning tokens no longer need to be encrypted at the endpoint).
For the purposes of this article, we’ll be referring to OAuth 2.0 as OAuth.
Defining OAuth RolesLink to this section
Roles are a key part of the OAuth protocol. These roles enable the authorization process to happen seamlessly and securely.
OAuth roles can be broken down into four key categories:
- Resource Owner: this tends to be the user that authorizes an app to access their account. Usually, access is limited and apps will only be given read or write access.
- Resource Server: this server hosts a user’s accounts or data.
- Client: this is an app that requests access to a user’s account or data. For this to happen, a user must authorize access and this authorization also needs to be validated by an API.
- Authorization Server: this server’s role is to verify the user’s identity and issue access tokens to the app.
Access tokens and authorization codesLink to this section
While OAuth roles are important, another key part of the authorization process is access tokens and authorization codes.
Access tokens are pieces of code that contain huge amounts of data about users, acting as the key that gives apps access to an API. These tokens are passed from a server to a user’s device, working to verify a user’s right to access specific resources.
Each access token contains these three core components:
- Header: data about the token’s type and which algorithm was used to create it.
- Payload: specific details about the user (such as their access permissions and expirations).
- Signature: confirms the authenticity of the token through verification data that is hashed and difficult to hack.
Interestingly, access tokens are standardized and don’t need to follow any particular format. However, these tokens are key to the security model of OAuth, including:
- The OAuth client isn’t the intended audience of the token. That means these tokens can’t be read or interpreted by the client.
- These tokens don’t share the identity of the user with the client.
- Plus, tokens should only be used to make requests to the resource server.
So, how are these access tokens created? That’s where authorization codes come in.
These are temporary codes that clients exchange for access tokens. Each code is provided from an authorization server, giving the user the ability to see what kind of information the client is requesting. At this point, a user can approve the request or even deny the request.
The ‘what’ and ‘how’ of OAuth flowsLink to this section
Flows are the processes that enable authorization through OAuth. Some flows need users to enter their login credentials via an OAuth login prompt, while others happen seamlessly in the backend without any input from the user.
Types of OAuth flowsLink to this section
By learning what type of OAuth flows exist, you can start to figure out which might be the right fit for your particular use case.
Authorization code flowsLink to this section
As the name suggests, authorization code flows enable an authorization code to be exchanged for an access token. To make this happen, you need to share your app’s client secret (a fixed string of code used in all API requests known only to you and the authorization server).
Use case: Typically, this flow is used for server-side web apps where the source code isn’t publicly exposed.
An authorization code flow works like this:
- A user navigates to the login link in a web app.
- This user is redirected to an OAuth authorization server where an OAuth login prompt is displayed.
- The user enters their login details.
- Then, the user is shown a list of permissions that they can grant the web app.
- Once they’ve made their selection, the user is redirected to the app. At the same time, the authorization server issues a one-time authorization code.
- The app receives this authorization code and shares it (along with the client ID and client secret) with the OAuth authorization server.
- The authorization server creates an ID token, access token and refresh token (optional) before sharing them with the app,
- Now, the app can use this access token to access the target API with the user’s credentials.
Client credentials flowLink to this section
This flow allows an app to pass its client secret and client ID to an authorization server. This authenticates a user and returns an access token.
Use case: Typically used by machine-to-machine apps, allows authentication and permissions to be granted without involving the user (because the ‘user’ is often a machine or service role).
A client credentials flow works like this:
- An app authenticates with an OAuth authorization server, sharing the client secret and client ID.
- Then, the authorization server reviews these details and returns an access token to the app.
- This access token allows the app to access the target API with the required user account.
Resource owner password flowLink to this section
While this OAuth flow is an option, it’s generally not recommended. That’s because it asks users to submit their login details via a form, with these details saved in the backend and retained for future use before an access token is granted.
Use case: Typically only for highly-trusted apps where flows based on redirects can’t be used.
A resource owner password flow works like this:
- A user clicks on a login link in an app and enters their details into a form, managed by the app.
- These details are stored by the app and passed onto the OAuth authorization server.
- The authorization server validates these credentials and creates an access token.
- Now, the app can access the target API with a user’s credentials.
Implicit flow with form postLink to this section
This flow harness OIDC (OpenID Connect) to enable a web sign-in. This means a web app requests and receives tokens via the front channel (removing the need for extra backend calls or secrets).
Use case: Best for apps that aren’t keen on maintaining secrets locally.
Hybrid flowLink to this section
If you’re looking to securely retain client secrets, this is a flow to consider. A hybrid flow allows your app to gain immediate access to an ID token, along with ongoing retrieval of both access and refresh tokens.
Use case: Best for apps that are looking for instant access to user data, while also needing to use this data on a regular, ongoing basis.
Device authorization flowLink to this section
This flow works without asking users for their login credentials. It offers a streamlined user experience for mobile devices - say goodbye to typing on a small screen. It allows apps to transfer their client ID to the device authorization flow to start the authorization process and ultimately obtain a token.
Use case: Best for apps running on input-constrained details that are online and apps looking for seamless authentication via credentials already sorted on a device.
Authorization code flow with PKCELink to this section
At the core of this flow is a proof key for code exchange (or PKCE for short). A secret, known as a code verifier, is shared by a calling app which is verified by the authorization server using a proof key.
Use case: Best for apps that are working with unknown public clients who could pose additional security risks that aren’t already addressed in the auth code flow.
Which OAuth flow is right for you?Link to this section
For most, your app type will determine which kind of OAuth flow is the best fit. Plus, it’s important to factor in other key elements like the client’s level of trust and your desired user experience.
Here are a few questions that can help you narrow down your options:
- Is the client the resource owner? Are they a human or a machine?
- Purely machine-driven authorization means the client is the same as the resource owner. If that’s the case, a client credentials flow will be a good fit.
- Is the client a web app executing on the server?
- If yes, you should opt for the authorization flow as it provides an access token directly to the client and reduces the chance of exposure along the way.
- Is the client completely trusted with user credentials?
- If yes, then the resource owner password flow will work (as long as the client is completely trusted).
- Is the client a single-page app (SPA)?
- A browser-based app like this, the preferred option is an authorization code flow with PKCE as the client-side access token.
- Is the client a native mobile app?
- The best choice here is the PKCE authorization flow.
If you’re looking for the accepted industry standard for online authorization, look no further than OAuth 2.0. It’s the key that provides consent access to apps on behalf of users while keeping their login credentials safe and secure.