Integrations
Auth Providers
OAuth 2.0

OAuth 2.0 auth provider

The OAuth 2.0 auth provider enables tools and agents to authorize with any OAuth 2.0-compatible API on behalf of a user. Behind the scenes, the Arcade Engine and this auth provider seamlessly manage OAuth 2.0 authorization for your users.

Arcade AI has pre-built integrations with many popular OAuth 2.0 providers. Use this OAuth 2.0 provider to connect to other systems that aren't pre-built.

What's documented here

This page describes how to configure OAuth 2.0 with Arcade AI, and use it in:

  • Your app code that needs to call APIs protected by OAuth 2.0
  • Or, your custom tools that need to call APIs protected by OAuth 2.0

Configuring OAuth 2.0

How you configure the OAuth 2.0 provider depends on whether you use the Arcade Cloud Engine or a self-hosted Engine.

Configuring OAuth 2.0 with the Arcade Cloud Engine

Coming soon! In 0.1.0-preview, the Arcade Cloud Engine does not yet support configuring auth providers.

Configuring OAuth 2.0 with a self-hosted Arcade Engine

Set environment variables

Set the following environment variables. Replace HOOLI with the name of the OAuth 2.0 provider you are configuring:

export HOOLI_CLIENT_ID="<your client ID>"
export HOOLI_CLIENT_SECRET="<your client secret>"

Or, you can set these values in a .env file:

HOOLI_CLIENT_ID="<your client ID>"
HOOLI_CLIENT_SECRET="<your client secret>"

See configuration for more information on how to set environment variables and configure the Arcade Engine.

Edit the Engine configuration

Edit the engine.yaml file and add a new item to the auth.providers section:

auth:
  providers:
    - id: hooli
      type: oauth2
      description: "Hooli OAuth 2.0 provider"
      enabled: true
      client_id: ${env:HOOLI_CLIENT_ID}
      client_secret: ${env:HOOLI_CLIENT_SECRET}
      oauth2:
        # Server-specific configuration, see reference below

The ID of the provider (hooli in this example) can be any string. It's used to reference the provider in your app code and must be unique.

Each service expects a slightly different set of parameters in the oauth2 section. Refer to the configuration reference below, and to your service's documentation to understand what parameters are required.

If you need help configuring a specific provider, get in touch with us!

Configuration reference

The only supported OAuth 2.0 flow is the authorization code grant (with or without PKCE).

scope_delimiter (optional, default " " / space): The delimiter for scopes, if any.

pkce (optional):

  • enabled (optional, default false): If true, PKCE will be used.
  • code_challenge_method (optional, default S256): The code challenge method to use. The only supported method is S256. This parameter is ignored if PKCE is not enabled.

authorize_request

This section configures the initial authorization request.

  • endpoint: The authorization endpoint for your OAuth 2.0 server, e.g. /oauth/authorize
  • params: A map of parameter keys and values to include in the authorization request.

These placeholders are available in params:

  • {{client_id}}: The configured client ID.
  • {{redirect_uri}}: The redirect URI managed by Arcade AI.
  • {{scopes}}: The scopes to request, if any
  • {{existing_scopes}}: The scopes that the user has already granted, if any.

The state parameter is automatically added to the request, and does not need to be included in params. If PKCE is enabled, code_challenge and code_challenge_method are also added automatically.

For most providers, oauth2.authorize_request.params will look like:

authorize_request:
  params:
    response_type: "code"
    client_id: "{{client_id}}"
    redirect_uri: "{{redirect_uri}}"
    scope: "{{scopes}} {{existing_scopes}}"

Some providers support additional parameters in the authorization request. These can be added to params as well. For example:

authorize_request:
  params:
    response_type: "code"
    client_id: "{{client_id}}"
    redirect_uri: "{{redirect_uri}}"
    scope: "{{scopes}} {{existing_scopes}}"
    prompt: "consent"
    access_type: "offline"

token_request

This section configures the code/token exchange request, after the user has approved access to your app.

  • endpoint: The token endpoint for your OAuth 2.0 server, e.g. /oauth/token
  • auth_method (optional, default none): The authentication method to use. Supported values are none (omitted) and client_secret_basic.
  • params: A map of parameter keys and values to include in the token request.

These placeholders are available in params:

  • {{client_id}}: The configured client ID.
  • {{client_secret}}: The configured client secret.
  • {{redirect_uri}}: The redirect URI managed by Arcade AI.

The code parameter is automatically added to the request, and does not need to be included in params. If PKCE is enabled, the code_verifier parameter is also added to the request automatically.

For most providers, oauth2.token_request.params will look like:

token_request:
  params:
    grant_type: "authorization_code"
    redirect_uri: "{{redirect_uri}}"
    client_id: "{{client_id}}"
    client_secret: "{{client_secret}}" # Omit if using PKCE
  • response_content_type (optional, default application/json): The expected content type of the response. Supported values are application/json and application/x-www-form-urlencoded.
  • response_map (optional): A map of keys and values to extract from the response. Supports simple JSONPath expressions. Only applicable if response_content_type is application/json. See the JSONPath reference for details on extracting values using JSONPath.

refresh_token_request

This section configures the refresh token request, if your OAuth 2.0 server supports refresh tokens. If not provided, refresh tokens will not be used.

  • endpoint: The refresh token endpoint for your OAuth 2.0 server, e.g. /oauth/token
  • auth_method (optional, default none): The authentication method to use. Supported values are none (omitted), client_secret_basic, and bearer_access_token.
  • params: A map of parameter keys and values to include in the refresh token request.

These placeholders are available in params:

  • {{refresh_token}}: The refresh token to use.
  • {{client_id}}: The configured client ID.
  • {{client_secret}}: The configured client secret.

For most providers, oauth2.refresh_token_request.params will look like:

refresh_token_request:
  params:
    grant_type: "refresh_token"
    client_id: "{{client_id}}"
    client_secret: "{{client_secret}}"
  • response_content_type (optional, default application/json): The expected content type of the response. Supported values are application/json and application/x-www-form-urlencoded.
  • response_map (optional): A map of keys and values to extract from the response. Supports simple JSONPath expressions. Only applicable if response_content_type is application/json. See the JSONPath reference for details on extracting values using JSONPath.

user_info_request

Some OAuth 2.0 APIs provide a user info endpoint that returns information about the user. Arcade Engine can automatically request user info from servers that support it. If the user_info_request section is omitted, user info will not be requested.

  • endpoint: The user info endpoint for your OAuth 2.0 server, e.g. /oauth/userinfo
  • auth_method (optional, default bearer_access_token): The authentication method to use. The only supported value is bearer_access_token.
  • response_content_type (optional, default application/json): The expected content type of the response. The only supported value is application/json.
  • triggers: Controls when the user info request is made.
    • on_token_grant: If true, the user info request will be made when a token is granted. This is typically only once for each user, unless new scopes are granted.
    • on_token_refresh: If true, the user info request will be made every time a token is refreshed.

JSONPath expressions in response_map

In the token_request and refresh_token_request sections, you can optionally configure response_map. Configuring response_map is useful if your OAuth 2.0 server returns a JSON object with nested properties, or properties with non-standard names.

The typical JSON payload that most OAuth 2.0 servers return looks like this:

{
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": 3600,
  "scope": "scope1 scope2"
}

If your server returns the above payload, you don't need response_map.

But if your server returns:

{
  "data": {
    "access_token": "...",
    "expires_in": 3600,
    "refresh_token": "...",
    "scope": "scope1 scope2"
  }
}

Then you need to configure response_map to extract the properties from inside the data object. Use JSONPath (opens in a new tab) expressions to select the properties you need:

token_request: # or refresh_token_request
  response_map:
    access_token: "$.data.access_token"
    expires_in: "$.data.expires_in"
    refresh_token: "$.data.refresh_token" # Only needed if refresh tokens are used
    scope: "$.data.scope" # Only needed if scopes are used

Not all OAuth 2.0 servers support refresh tokens, or use scopes. The only required properties are access_token and expires_in.

Joining scopes in response_map

Most OAuth 2.0 servers return scopes as a delimited string, such as scope1 scope2 or scope1,scope2. If your server follows this convention, configuring the top-level scope_delimiter property in the oauth2 section is all you need to do.

Some OAuth 2.0 servers return an array of scopes instead of a delimited string. For example:

{
  "access_token": "...",
  "expires_in": 3600,
  "scope": ["scope1", "scope2"]
}

In this case, you need to use the join() function in response_map to join the scopes into a delimited string:

token_request:
  response_map:
    access_token: "$.access_token"
    expires_in: "$.expires_in"
    scope: "join('$.scope', ' ')"

join() takes two arguments:

  • path: The JSONPath expression to select the array to join.
  • delimiter: The delimiter to use between array elements. Make sure this matches the scope_delimiter setting in the oauth2 section.

Full configuration example

Here's a full example of the YAML configuration for a custom OAuth 2.0 provider:

Using OAuth 2.0 in app code

Use the OAuth 2.0 auth provider in your own agents and AI apps to get a user token for any OAuth 2.0-compatible APIs. See authorizing agents with Arcade to understand how this works.

Use client.auth.start() to get an access token:

from arcadepy import Arcade
 
client = Arcade()  # Automatically finds the `ARCADE_API_KEY` env variable
 
 
user_id = "[email protected]"
 
# Start the authorization process
auth_response = client.auth.start(
    user_id=user_id,
    provider="hooli",
    scopes=["scope1", "scope2"],
)
 
if auth_response.status != "completed":
    print("Please complete the authorization challenge in your browser:")
    print(auth_response.authorization_url)
 
# Wait for the authorization to complete
auth_response = client.auth.wait_for_completion(auth_response)
 
token = auth_response.context.token
# TODO: Do something interesting with the token...

Using OAuth 2.0 in custom tools

The Arcade LLM API is a convenient way to call LLMs and automatically invoke tools. You can author your own custom tools that interact with any OAuth 2.0-compatible APIs.

Use the OAuth2() auth class to specify that a tool requires OAuth 2.0 authorization. In your tool function, context.authorization will be automatically populated with the following properties:

  • context.authorization.token contains the user's access token.
  • If oauth2.user_info_request is configured, the user info will be fetched and placed in context.authorization.user_info. The data payload is specific to each provider.
from typing import Annotated
 
from arcade.sdk import ToolContext, tool
from arcade.sdk.auth import OAuth2
 
 
@tool(
    requires_auth=OAuth2(
        provider_id="hooli",
        scopes=["scope1", "scope2"],
    )
)
async def reticulate_splines(
    context: ToolContext,
    num_splines: Annotated[int, "The number of splines to reticulate"],
):
    """Reticulate the specified number of splines."""
 
    # Get an access token to call an API
    token = context.authorization.token
 
    # Get user info (if configured and supported by the OAuth 2.0 server):
    user_id = context.authorization.user_info.get("sub")