Skip to main content
b0e673ba3e339b31ac36dc3cd004df04787bcaa64bb6d2cac6feb7152b7b515f.png This guide teaches you how to build OAuth support into your tool plugin. OAuth is a better way to authorize tool plugins that need to access user data from third-party services, like Gmail or GitHub. Instead of requiring the user to manually enter API keys, OAuth lets the tool act on behalf of the user with their explicit consent.

Background

OAuth in Dify involves two separate flows that developers should understand and design for.

Flow 1: OAuth Client Setup (Admin / Developer Flow)

On Dify Cloud, Dify team would create OAuth apps for popular tool plugins and set up OAuth clients, saving users the trouble to configure this themselves.Admins of Self-Hosted Dify instances must go through this setup flow.
Dify instance’s admins or developers first need to register an OAuth app at the third-party service as a trusted application. From this, they’ll be able to obtain the necessary credentials to configure the Dify tool provider as an OAuth client. As an example, here are the steps to setting up an OAuth client for Dify’s Gmail tool provider:
  1. Go to Google Cloud Console and create a new project, or select existing one
  2. Enable the required APIs (e.g., Gmail API)
  1. Go to APIs & Services > Credentials
  2. Click Create Credentials > OAuth 2.0 Client IDs
  3. Choose Web application type
  4. Aclient_id and aclient_secret will be generated. Save these as the credentials.
Enter the client_id and client_secret on the OAuth Client configuration popup to set up the tool provider as a client.acd5f5057235c3a0c554abaedcf276fb48f80567f0231eae9158a795f8e1c45d.png
Register the redirect URI generated by Dify on the Google OAuth Client’s page:dfe60a714a275c5bf65f814673bd2f0a0db4fda27573a2f0b28a1c39e4c61da2.png
Dify displays the redirect_uri in the OAuth Client configuration popup. It usually follows the format:
https://{your-dify-domain}/console/api/oauth/plugin/{plugin-id}/{provider-name}/{tool-name}/callback
For self-hosted Dify, the your-dify-domain should be consistent with the CONSOLE_WEB_URL.
Each service has unique requirements, so always consult the specific OAuth documentation for the services you’re integrating with.

Flow 2: User Authorization (Dify User Flow)

After configuring OAuth clients, individual Dify users can now authorize your plugin to access their personal accounts. 833c205f5441910763b27d3e3ff0c4449a730a690da91abc3ce032c70da04223.png

Implementation

1. Define OAuth Schema in Provider Manifest

The oauth_schema section of the provider manifest definitions tells Dify what credentials your plugin OAuth needs and what the OAuth flow will produce. Two schemas are required for setting up OAuth:

client_schema

Defines the input for OAuth client setup:
gmail.yaml
oauth_schema:
  client_schema:
    - name: "client_id"
      type: "secret-input"
      required: true
      url: "https://developers.google.com/identity/protocols/oauth2"
    - name: "client_secret"
      type: "secret-input" 
      required: true
The url field links directly to help documentations for the third-party service. This helps confused admins / developers.

credentials_schema

Specifies what the user authorization flow produces (Dify manages these automatically):
# also under oauth_schema
  credentials_schema:
    - name: "access_token"
      type: "secret-input"
    - name: "refresh_token"
      type: "secret-input"
    - name: "expires_at"
      type: "secret-input"
Include both oauth_schema and credentials_for_provider to offer OAuth + API key auth options.

2. Complete Required OAuth Methods in Tool Provider

Add these imports to where your ToolProvider is implemented:
from dify_plugin.entities.oauth import ToolOAuthCredentials
from dify_plugin.errors.tool import ToolProviderCredentialValidationError, ToolProviderOAuthError
Your ToolProvider class must implement these three OAuth methods (taking GmailProvider as an example):
Under no circumstances should the client_secret be returned in the credentials of ToolOAuthCredentials, as this could lead to security issues.
def _oauth_get_authorization_url(self, redirect_uri: str, system_credentials: Mapping[str, Any]) -> str:
	"""
	Generate the authorization URL using credentials from OAuth Client Setup Flow. 
    This URL is where users grant permissions.
    """
    # Generate random state for CSRF protection (recommended for all OAuth flows)
    state = secrets.token_urlsafe(16)
    
    # Define Gmail-specific scopes - request minimal necessary permissions
    scope = "read:user read:data"  # Replace with your required scopes
    
    # Assemble Gmail-specific payload
    params = {
        "client_id": system_credentials["client_id"],    # From OAuth Client Setup
        "redirect_uri": redirect_uri,                    # Dify generates this - DON'T modify
        "scope": scope,                                  
        "response_type": "code",                         # Standard OAuth authorization code flow
        "access_type": "offline",                        # Critical: gets refresh token (if supported)
        "prompt": "consent",                             # Forces reauth when scopes change (if supported)
        "state": state,                                  # CSRF protection
    }
    
    return f"{self._AUTH_URL}?{urllib.parse.urlencode(params)}"

3. Access Tokens in Your Tools

You may use OAuth credentials to make authenticated API calls in your Tool implementation like so:
class YourTool(BuiltinTool):
    def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
        if self.runtime.credential_type == CredentialType.OAUTH:
            access_token = self.runtime.credentials["access_token"]
        
        response = requests.get("https://api.service.com/data",
                              headers={"Authorization": f"Bearer {access_token}"})
        return self.create_text_message(response.text)
self.runtime.credentials automatically provides the current user’s tokens. Dify handles refresh automatically. For plugins that support both OAuth and API_KEY authentication, you can use self.runtime.credential_type to differentiate between the two authentication types.

4. Specify the Correct Versions

Previous versions of the plugin SDK and Dify do not support OAuth authentication. Therefore, you need to set the plugin SDK version to:
dify_plugin>=0.4.2,<0.5.0.
In manifest.yaml, add the minimum Dify version:
meta:
  version: 0.0.1
  arch:
    - amd64
    - arm64
  runner:
    language: python
    version: "3.12"
    entrypoint: main
  minimum_dify_version: 1.7.1

Edit this page | Report an issue