Skip to main content

OAuth2 fundamentals

OAuth2 is an authorization framework that enables applications to access user accounts on an HTTP service. This document describes OAuth 2 roles, grant types, use cases, and flows, geared towards application developers. OAuth2 provides access to resources hosted by other web apps on behalf of a user, without sharing the user's credentials. The specification also covers delegated access to client types such as browser-based, server-side web, native/mobile apps, and connected devices.

OAuth2 actors

OAuth2 has different actors defined in the authentication and authorization process. These actors work together to ensure that the user's information is kept secure and that the application only accesses the information that the user has explicitly granted permission for.

The user: "resource owner"

The resource owner is the person or system that owns protected resources, such accounts, a files, or data, and has the ability to grant access to them. In the context of OAuth2 and OpenID Connect, the resource owner is typically a user who has an account in a service or application.

When an application wants to access a resource owner's account, it must first request authorization from the resource owner. The resource owner has the ability to limit the application's access to their account to a specific scope, such as read or write access. This means that the application can only access the user's account within the limits of the authorization granted.

For example, if a user wants to use an application that requires access to their email account, the user must first grant the application permission to access their account. The user can choose to grant access only to specific emails or folders, or limit the application's access to read-only mode. The resource owner is in complete control of who can access their account and what level of access they are granted.

With Ory OAuth2 and OpenID Connect, developers have the flexibility to use their own user management systems to store and manage resource owners, while still taking advantage of the robust authorization and authentication mechanisms provided by the OAuth2 and OpenID Connect protocols.

info

By default, Ory Identities is used to store and manage resource owners in the Ory Network.

The application: "OAuth2 client"

The OAuth2 client is the application that requires access to protected resources, such as a user's account details or data. Before the client can access these resources, it must first get an access token, which serves as proof of authorization to access the requested resources. The client must first be authorized by the resource owner and must hold a valid access token in order to access protected resources. The API server that hosts the protected resources will validate the access token to ensure that the client is authorized to access the requested resources.

The API: "resource server"

The resource server is a server that hosts and protects the user's resources, such as their account information or data. It is typically an API server that exposes a set of endpoints that allow clients to access the protected resources. The resource server receives access requests from the OAuth2 client and verifies the access token presented with the request to ensure that the request is authorized. If the access token is valid and authorized, the resource server returns the appropriate resources to the client. If the access token is invalid or unauthorized, the resource server returns an error message to the client.

The authorization server: Ory OAuth2 and OpenID Connect

The authorization server is a critical component in OAuth2 flows. It receives requests from the client for access tokens and issues them upon successful authentication and consent by the resource owner. The authorization server exposes two endpoints: the Authorization endpoint and the Token endpoint. The Authorization endpoint is responsible for handling the interactive authentication and consent of the user, while the Token endpoint is involved in a machine-to-machine interaction.

The Authorization endpoint is where the resource owner approves or denies the request from the client. This endpoint presents an interface to the resource owner that allows them to view the scope of the requested access and make an informed decision about whether to grant or deny access to their resources. In smaller implementations, the authorization server may be combined with the API server, but larger scale deployments will often build this as a separate component.

OAuth2 scope is a parameter used to specify the level of access that OAuth2 clients have to protected resources. It allows resource owners to define specific permissions or actions that a client is authorized to perform in their name.

Scopes are an important concept in OAuth2 as they are used to specify the exact level of access to resources that can be granted. For example, a scope may include read access to a user's email, write access to a user's calendar, or access to a specific set of files. The acceptable scope values, and which resources they relate to, are dependent on the resource server.

Ory OAuth2 and OpenID Connect has pre-defined OAuth2 scope values:

  • offline_access: Include this scope if you want to receive a refresh token
  • openid: Include this scope if you want to perform OpenID Connect requests.

Scopes vs permissions

What's the difference between scopes and permissions? Scopes define what the client is authorized to access in the name of the user. Permissions (RBAC, ACL) define what the user themselves are allowed to do. By using scopes, users can control the level of access that clients have to protected resources. Permissions ensure a user has access to their resources only, not the resources of other users.

OAuth2 access token audience

The audience of an access token are the resource servers that this token is intended for. The audience usually refers to one or more URLs such as

  • One or more URLs: https://api.mydomain.com/blog/posts, https://api.mydomain.com/users
  • A subset of resources: https://api.mydomain.com/tenants/foo/users

When performing an OAuth2 flows where the user is involved, for example Implicit Grant or Authorization Code Grant, the granted audience must be set when accepting the consent using the grant_access_token_audience key. In most cases, it's ok to grant the audience without user interaction.

Creating OAuth2 clients

Creating an OAuth2 client is a necessary step to enable your application to use OAuth2 flows. Before using OAuth with your application, you must register your application with the service you plan to integrate with. This is done through a registration form in the developer or API portion of the service's website, where you provide the following information about your application:

  • Application name
  • Application website
  • Redirect URI or callback URL.

The application name and website are basic pieces of information that identify your application. The redirect URI or callback URL is a crucial part of the registration process as it defines where the service redirects the user after the user authorizes (or denies) your application. The redirect URI is also where your application handles authorization codes or access tokens, making it an important component of the OAuth2 flow.

It is important to ensure that the redirect URI or callback URL is correctly specified during the registration process, as it's a critical part of OAuth2 flows. Without a correctly specified redirect URI, OAuth2 flows can't be completed successfully, resulting in an error for the user.

Client ID and secret

After you register your application with the service, you typically receive a client ID and optionally a client secret from the authorization server. These are unique identifiers that allow the authorization server to identify your application and allow it to access protected resources. The client ID is considered public information and can be included in JavaScript source code or used to build login URLs. The client secret, however, must be kept confidential and is used to authenticate the client to the authorization server.

The token_endpoint_auth_method parameter is an optional parameter used to specify the client authentication method when requesting an access token. This parameter is included in the request to the token endpoint and can be set to a variety of values, including client_secret_basic (default), client_secret_post, and none. The value of this parameter can affect how the client authenticates itself to the authorization server.

For example, if the value of the token_endpoint_auth_method parameter is set to client_secret_basic, the client authenticates itself to the authorization server by including the client ID and client secret in the Authorization header of the request:

POST /oauth2/token
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(urlencoded(id):urlencoded(secret))

If the value of the token_endpoint_auth_method parameter is set to client_secret_post, the client authenticates itself to the authorization server by including the client ID and client Secret in the form body of the request:

POST /oauth2/token
Content-Type: application/x-www-form-urlencoded

client_id=id&client_secret=secret

The none method is typically used for public clients, such as Single-Page Applications (SPAs) and mobile apps, which are not capable of keeping a client secret confidential. When the token_endpoint_auth_method parameter is set to none, the client doesn't include any credentials when requesting an access token. This means that the client relies solely on the redirect URI to securely receive the access token, rather than using a shared secret to authenticate itself to the authorization server.

Getting a client token

OAuth2 defines several grant types, each of which is intended for a specific type of client application.

Client credentials flow

The client credentials flow is designed for non-interactive applications, such as automated processes or microservices, where the client is authenticated using its client ID and client secret. In this flow, the application sends a POST request to the authorization server, including its credentials and a request for an access token. If the credentials are verified, the authorization server returns an access token to the application, which can then use it to access its own account.

For more information, see the Client Credentials Flow.

Authorization Code Flow

The Authorization Code Flow, is the most commonly used OAuth2 flow. It's optimized for server-side applications where client secret confidentiality can be maintained. In this flow, the user is first presented with an authorization code link that includes the application's client ID and other parameters, such as the redirect URI and the requested scope of access. After the user approves the application, the service redirects the user-agent to the redirect URI specified by the application, including an authorization code. The application then exchanges this code, along with its client secret, for an access token using the token endpoint.

It's worth noting that in this flow, the client secret cannot be stored securely, since it needs to be included in the request to the token endpoint. For this reason, single-page applications and mobile/native apps are often not appropriate for this flow, and should instead use the authorization code with PKCE grant. In addition, the scope parameter is used to specify the level of access that the application is requesting, and acceptable scope values are dependent on the resource server. Overall, the authorization code flow is a redirection-based flow that relies on the user-agent (the user's web browser) and API authorization codes to securely handle authentication and consent.

For more information, see the OAuth2 Authorization Code Flow.

Use case examples

Server-side web apps

Server-side web applications, such as those built with Node.js or PHP, are typically best suited to using the OAuth2 Authorization Code Flow. This is because server-side applications can keep the client secret confidential, which is necessary for using the Authorization Code Flow.

In addition, it's recommended that server-side web applications use the Authorization Code Flow with the Proof Key for Code Exchange (PKCE) extension to provide an added layer of security. The PKCE extension helps to mitigate the risk of attacks by requiring the client to generate a code verifier for every authorization request, which is then transformed into a code challenge and sent to the authorization endpoint along with the request.

Mobile apps

The OAuth2 Authorization Code Flow is the recommended flow to use with mobile applications. Because mobile apps are considered public clients, it's highly recommended to use the Authorization Code Flow with the PKCE extension.

Single-page apps

Single-page applications (SPAs) are web applications that run inside a web browser and dynamically update the page as the user interacts with the application. Because the client-side code of an SPA is fully exposed to the user, it's not safe to store a client secret in the application. As a result, SPAs should also use the OAuth2 Authorization Code Flow flow with PKCE to ensure the client secret is not exposed.

For example, an SPA that uses OAuth2 to access Google APIs would use the Authorization Code Flow with PKCE. When the user clicks the "Sign in with Google" button, the SPA redirects the user to Google's authorization endpoint, where they are prompted to grant permission for the application to access their Google account. If the user grants permission, Google will return an authorization code to the SPA. The application can exchange the code for an access token using the token endpoint. The SPA can then use the access token to access the user's data through Google APIs. By using PKCE, the SPA can ensure that the authorization code cannot be intercepted and used by an attacker.

Smart devices

The Device Code Flow is designed for devices that have limited inputs or do not have a web browser, and need to obtain an access token to access a user's account. This grant type provides an easier way for users to authorize applications on such devices to access their accounts. It is particularly useful in scenarios where users want to sign in to an application on a device that lacks a typical keyboard input, such as a smart TV or video game console.

With the Device Code grant type, the user initiates the flow on a separate device, such as a phone or computer, and is presented with a Device Code. The user then enters this code on the device that needs to obtain the access token. This device will periodically poll the authorization server until the user grants or denies the authorization request. Once the user grants access, the device receives an access token that can be used to access the user's account.

Accessing APIs

Sending an access token to a resource server usually involves including the token in the HTTP Authorization header of the request. Here's an example code snippet in JavaScript that shows how to do this:

const fetch = require("node-fetch")
const accessToken = "your_access_token_here"

fetch("https://api.example.com/resource", {
headers: {
Authorization: "Bearer " + accessToken,
},
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error(error))

In this example, the access token is included in the Authorization header of the GET request sent to the resource server API endpoint. The Bearer keyword indicates that the token is a bearer token, which is a type of access token that can be used by any client to access the protected resources. The resource server then verifies the token and grant or deny access based on the token's validity and the scope of access that was granted.

The resource server needs to ensure that the access token is valid and has not been tampered with or expired before allowing access to protected resources. To achieve this, the resource server uses the OAuth2 token introspection endpoint, which is an API endpoint exposed by Ory.

Resource Owner Password Credentials flow

Ory doesn't support the resource owner Password Credentials Grant Type as we prepare for OAuth 2.1 which removed this grant type.

Implicit flow

As the industry has evolved, so has the best practice for implementing OAuth2 in mobile and native apps. Previously, the Implicit grant was recommended, but it has since been found to be less secure. The current recommendation is to use the Authorization Code with PKCE for native apps, which provides greater security for both the user and the application.