Auth Concepts

Understand the core concepts behind Composio Auth

Composio Auth simplifies integrating user-authorized actions into your app. It securely manages OAuth flows, handles token storage, and ensures actions are executed with the correct user’s credentials.

Composio Auth relies on three core concepts. Integration, Connection, Entities.

Composio Auth Concepts showing the relationship between Integration, Connection, and Entity

About authentication and authorization

Authentication means checking that a user is who they say they are. This is about establishing WHO the user is.

For example, when a user connects their Gmail account to your app, Composio Auth guides the user through Google’s OAuth login. The user securely proves their identity to Google, and Composio safely stores the resulting access token, confirming the user’s identity without you handling sensitive credentials.

On expiry, Composio Auth automatically refreshes the access token, ensuring continuous, secure access without requiring users to re-authenticate.

Authorization means checking what resources a user can access. This is about controlling WHAT the authenticated user can do.

Continuing the Gmail example, authorization happens when your app attempts to access a user’s inbox. Scopes are used to control what resources a user can access. The application controls access to the resources based on the scopes requested during authentication.

Explained below are some authentication schemes that Composio supports.

OAuth 2.0 allows users to securely grant limited permissions to your app for accessing their data on third-party services without sharing actual login credentials.

Composio Auth streamlines OAuth by managing user authorization, token handling, secure storage, and token refreshing.

OAuth 2.0 Flow:

OAuth uses Scopes to define the exact permissions your app needs (e.g., mail.read for Gmail). Composio helps ensure secure, precise configuration of scopes.

API Keys are simple credentials used to directly access services, usually with broad access privileges.

Composio securely stores API keys, automatically applying them to API requests, providing secure yet straightforward access.

API Key Flow:

Bearer Tokens are credentials sent in HTTP headers to securely access protected resources without needing underlying user credentials.

Composio securely manages Bearer Tokens, embedding them in API requests automatically, simplifying secure token handling.

Bearer Token Flow:

Basic Authentication encodes and sends user credentials (username and password) with each request.

Composio securely encodes and handles these credentials, managing headers securely, ensuring sensitive data protection.

Basic Authentication Flow:

JWT is a compact, secure method for encoding user information, claims, and permissions for safe transmission between systems.

Composio manages JWT lifecycle, including creation, validation, verification of signatures, expiration handling, and secure storage.

JWT Flow:

Integration

An Integration in Composio is a configuration that connects your app to third-party services like GitHub, Google Drive, or Slack. It contains all the authentication details (OAuth 2.0, API Key, or JWT) and service-specific settings needed to create secure connections for your users.

Essentially, for each third-party service, you only need one integration that manages multiple users.

An Integration stores all necessary authentication and API communication details required for making authenticated requests to third-party services. These properties define how Composio interacts with the external API.

PropertyDescription
Base URLThe root endpoint for all API calls.
ScopesThe scopes required for the integration.
Authentication SchemeDefines the supported authentication methods, such as API Key, OAuth 2.0, or JWT.
Callback URLThe endpoint for handling authentication responses and obtaining JWT tokens (if applicable).
Authorization ParametersCustom parameters required when initiating authentication.
Token ParametersParameters needed to retrieve and refresh access tokens.
API EndpointsA list of necessary endpoints used for executing tool calls.

Composio supports multiple authentication schemes, and each Integration can define one or more of these:

Authentication MethodDescription
OAuth 2.0Requires an authorization URL, token URL, and scopes for user authentication.
OAuth 1.0An older version of OAuth, requiring a request token and access token for user authentication.
API KeyUses a static API key, optionally with an API secret, included in request headers or query parameters.
Basic AuthenticationRequires a username and password for authentication, typically sent in an Authorization header.
Bearer TokenUses a token in the Authorization header, often retrieved from OAuth 2.0 or another identity provider.
Basic with JWTA hybrid approach that combines basic authentication (username/password) with JWT-based token authentication.
No AuthenticationSome APIs do not require authentication, allowing open access to endpoints.
  • Developers configure Integrations once per third-party service.
  • Users authenticate against these Integrations to establish personalized connections.
  • API calls are routed through Composio, leveraging stored authentication details for seamless execution.

Creating Integrations

Below code snippet some helper functions while working with integrations.

1

Listing and checking existing integrations

1from typing import Any
2from composio_openai import ComposioToolSet, App, Action
3from composio.client.collections import IntegrationModel
4from composio.client.collections import AuthSchemeType
5
6toolset = ComposioToolSet()
7
8
9def has_integration(app: App) -> bool:
10 """
11 Check if an integration exists for the given app.
12 """
13 integrations = toolset.get_integrations(app=app)
14 return len(integrations) > 0
15
16print(has_integration(App.ASANA)) # Check for any valid Composio App
2

(Optional) Specifying Client Credentials

For OAuth 2.0 integrations where it is recommended to provide your own client credentials read: OAuth Client Credentials, you can specify your client credentials while creating the integration.

First view the expected params

1app = toolset.client.apps.get(name="gmail")
2expected_params = toolset.fetch_expected_integration_params(
3 app=app,
4 auth_scheme="OAUTH2",
5)
6print(expected_params)
1{
2 "name": "client_id",
3 "display_name": "Client id",
4 "description": "Client id of the app",
5 "type": "string",
6 "default": null,
7 "required": true,
8 "expected_from_customer": false,
9 "get_current_user_endpoint": null
10}
11{
12 "name": "client_secret",
13 "display_name": "Client secret",
14 "description": "Client secret of the app",
15 "type": "string",
16 "default": null,
17 "required": true,
18 "expected_from_customer": false,
19 "get_current_user_endpoint": null
20}
21{
22 "name": "oauth_redirect_uri",
23 "display_name": "Redirect URI",
24 "description": "Add this Redirect URL to your app's OAuth allow list.",
25 "type": "string",
26 "default": "https://backend.composio.dev/api/v1/auth-apps/add",
27 "required": false,
28 "expected_from_customer": false,
29 "get_current_user_endpoint": null
30}
31{
32 "name": "scopes",
33 "display_name": "Scopes",
34 "description": "Scopes to request from the user, comma separated",
35 "type": "string",
36 "default": "https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/userinfo.profile",
37 "required": false,
38 "expected_from_customer": false,
39 "get_current_user_endpoint": null
40}
3

Creating the Integration

Parameters (Python/TypeScript)Expected ValuesDescription
app / appUniqueKeyName of the app. Eg: GITHUB, NOTION, GMAILSpecifies the target app for the integration
auth_mode / authSchemeOAUTH2, OAUTH1, API_KEY, BASIC, BEARER_TOKEN, BASIC_WITH_JWT, NO_AUTHDefines the authentication method for the integration.
use_composio_oauth_app / useComposioAuthTrue or FalseDetermines whether to use Composio’s managed OAuth app instead of your own credentials.
force_new_integrationTrue or FalseForces the creation of a new integration instead of using an existing one.
auth_configDictionary/object containing values like client_id, client_secret, redirect_uri, etc.Contains authentication configuration details specific to the chosen auth scheme.
1{
2 "id": "00000000-0000-0000-0000-000000000000",
3 "name": "github_1",
4 "authScheme": "OAUTH2",
5 "createdAt": "2025-03-19T09:06:24.181Z",
6 "updatedAt": "2025-03-19T09:06:24.181Z",
7 "enabled": true,
8 "deleted": false,
9 "appId": "01e22f33-dc3f-46ae-b58d-050e4d2d1909",
10 "appName": "github",
11 "expectedInputFields": [],
12 "logo": "https://cdn.jsdelivr.net/gh/ComposioHQ/open-logos@master/github.png",
13 "defaultConnectorId": "test-github-connector",
14 "connections": null
15}
1def create_integration_if_not_exists(
2 app: App,
3 auth_mode: AuthSchemeType,
4 auth_config: dict,
5 use_composio_oauth_app: bool = False,
6 force_new_integration: bool = False,
7) -> IntegrationModel:
8 """
9 Create an integration if it doesn't exist.
10 """
11 if not force_new_integration and has_integration(app):
12 integrations = toolset.get_integrations(app=app)
13 return integrations[0]
14
15 integration = toolset.create_integration(
16 app=app,
17 auth_mode=auth_mode,
18 auth_config=auth_config,
19 use_composio_oauth_app=use_composio_oauth_app,
20 )
21 return integration
22
23integration = create_integration_if_not_exists(
24 app=App.GMAIL,
25 auth_mode="OAUTH2",
26 auth_config={"client_id": "1234567890", "client_secret": "1234567890"},
27 use_composio_oauth_app=False,
28)

Below is the full code to creating and managing an integration!

1from typing import Any
2from composio_openai import ComposioToolSet, App, Action
3from composio.client.collections import IntegrationModel
4from composio.client.collections import AuthSchemeType
5
6toolset = ComposioToolSet()
7
8
9def has_integration(app: App) -> bool:
10 """
11 Check if an integration exists for the given app.
12 """
13 integrations = toolset.get_integrations(app=app)
14 return len(integrations) > 0
15
16
17def create_integration_if_not_exists(
18 app: App,
19 auth_mode: AuthSchemeType,
20 auth_config: dict,
21 use_composio_oauth_app: bool = False,
22 force_new_integration: bool = False,
23) -> IntegrationModel:
24 """
25 Create an integration if it doesn't exist.
26 """
27 if not force_new_integration and has_integration(app):
28 integrations = toolset.get_integrations(app=app)
29 return integrations[0]
30
31 integration = toolset.create_integration(
32 app=app,
33 auth_mode=auth_mode,
34 auth_config=auth_config,
35 use_composio_oauth_app=use_composio_oauth_app,
36 )
37 return integration
38
39print(has_integration(App.GMAIL))
40
41app = toolset.client.apps.get(name="gmail")
42expected_params = toolset.fetch_expected_integration_params(
43 app=app,
44 auth_scheme="OAUTH2",
45)
46print(expected_params)
47
48integration = create_integration_if_not_exists(
49 app=App.GMAIL,
50 auth_mode="OAUTH2",
51 auth_config={"client_id": "1234567890", "client_secret": "1234567890"},
52 use_composio_oauth_app=False,
53)

Entity

An Entity in Composio serves as an abstraction over a user in your application. It represents an individual user and provides a structured way to manage their authenticated API interactions.

Instead of directly handling user authentication at the application level, Composio uses Entities to link users to their respective service connections.

  • User Identification: Entities allow you to manage users in Composio without directly dealing with user-specific authentication details.

  • Seamless Authentication: Each Entity can have multiple connections to third-party services, enabling secure API interactions on behalf of users.

  • Scoped API Execution: When executing API calls, the Entity ID ensures Composio applies the correct user’s authentication details.

Entity Management

Entities provide a set of methods that allow you to manage connections for each user efficiently.

ActionDescription
get_connectionRetrieves a specific connection for the entity, linked to a service.
get_connectionsLists all connections associated with the entity (e.g., Gmail, Notion, etc.).
initiate_connectionStarts the authentication flow for a user to establish a new connection.
1from composio_openai import ComposioToolSet
2toolset = ComposioToolSet()
3# Expected to fetch the entity ID from application logic
4entity = toolset.get_entity(id='default')

Once you create the Entity object, you can use it to handle tool calls and execute actions. Alternatively, you can specify the Entity ID itself while handling tool calls.

1result = toolset.handle_tool_calls(tool_request, entity_id="user_123")

In essence, an Entity in Composio is the mechanism that links your application’s user identity system with Composio’s connection management, enabling personalized API interactions on behalf of specific users.

Connection

A Connection in Composio represents an authenticated link between a specific entity and an external service through an Integration.

An integration can have multiple connections, each representing a different user’s authentication state.

It’s an abstraction that stores and manages your users’ auth configuration. Connections serve as the runtime authentication context that enables Composio to:

  1. Make authenticated API calls on behalf of specific users.
  2. Automatically refresh tokens before expiry.
  3. Associate API responses with the correct user.
For OAuth 2.0 based connections, Composio automatically refreshes the access token.

Creating Connections

To create a connection for an entity, you need to provide the auth scheme and the connection parameters.

Creating a connection in application level code requires some basic steps.

1

Fetch Integration ID and Entity

You need to fetch the entity_id from your database or application logic.

1from composio.client.collections import ExpectedFieldInput
2from composio.exceptions import NoItemsFound
3from composio_openai import App, ComposioToolSet
4
5toolset = ComposioToolSet()
6
7# Fetched from application logic
8user_id = "00000000-0000-0000-0000-000000000000"
9integration = toolset.get_integrations(App.GITHUB)[0] # or App.SHOPIFY
2

Check for an active connection

Here’s how to check for an active connection.

1def has_active_connection(user_id: str, app: App):
2 entity = toolset.get_entity(user_id)
3 try:
4 connection = entity.get_connection(app=app)
5 return connection.status == "ACTIVE"
6 except NoItemsFound:
7 return False
8
9if has_active_connection(user_id, App.GITHUB):
10 print("Connection already exists for this user")
11else:
12 print("\nSetting up new connection...")
3

Retrieve connection parameters

Connection parameters vary per integration. For example, OAUTH2 based integrations don’t require any additional parameters from the user, however other methods may require things like the Base URL or JWT token.

Pre-requisiteDescription
Auth SchemeOne of: OAUTH2, OAUTH1, API_KEY, BASIC, BEARER_TOKEN, BASIC_WITH_JWT, NO_AUTH
Connection ParametersOptional user-provided details based on the auth scheme. For example, if using API_KEY, the user may need to enter the API key and Base URL.

Fetching connection parameters with an integration ID

1def request_connection_params(integration_id: str):
2 return toolset.get_expected_params_for_user(integration_id=integration_id)
3
4conn_params = request_connection_params(integration.id)
5print(conn_params["expected_params"])

Fetching connection parameters with app and auth scheme

1def request_connection_params(app: App, auth_scheme: str):
2 return toolset.get_expected_params_for_user(app=app, auth_scheme)
3
4conn_params = request_connection_params(app=App.GMAIL, auth_scheme="BEARER_TOKEN")
5print(conn_params["expected_params"])
For integrations which supported auth schemes, the parameters for the configured auth schemes should be provided
4

Initiate Connection

ArgumentExpected ValuesDescription
app_name / appNamestr or App enumThe name or enum value of the application to connect to
auth_mode / authMode"OAUTH2", "OAUTH1", "OAUTH1A", "API_KEY", "BASIC", "BEARER_TOKEN", "GOOGLE_SERVICE_ACCOUNT", "NO_AUTH", "BASIC_WITH_JWT", "COMPOSIO_LINK" or NoneThe authentication mode to use
auth_config / authConfigDict[str, Any] or NoneAdditional authentication configuration parameters
redirect_url / redirectUristr or NoneURL to redirect to after authentication flow. Usually back to your app.
integration_id / integrationIdstr or NoneID of an existing integration to use
connection_params / connectionParamsDict[str, Any] or NoneParameters required for the connection
configDict containing optional labels and redirectUrlAdditional configuration options
labelsList[str] or NoneLabels to attach to the connection
use_composio_authboolWhether to use Composio’s OAuth apps. Defaults to True
force_new_integrationboolWhether to force creation of new integration. Defaults to False

Initializing a connection without parameters

1connection = entity.initiate_connection(
2 app_name=app,
3 use_composio_auth=False,
4 force_new_integration=True,
5 auth_mode=auth_mode,
6)

Initializing connection with parameters

It is recommended to check the connection parameters and then accept each field from the user within your application logic.

1def request_connection_params(app: App, integration_id: str):
2 return toolset.get_expected_params_for_user(integration_id=integration_id)
3
4def get_connection_values(connection_params_info: list[ExpectedFieldInput]):
5 print(
6 "\nTo connect to this service, you'll need to provide the following authentication details:"
7 )
8 connection_params = {}
9 for param in connection_params_info:
10 param_dict = param.model_dump()
11 # Collect input from user
12 value = input(f"Enter value for {param_dict['name']}: ")
13 connection_params[param_dict["name"]] = value
14 return connection_params
15
16def initiate_connection(
17 user_id: str, app: App, connection_params: dict, auth_mode: str, redirect_url: str
18):
19 entity = toolset.get_entity(user_id)
20 connection = entity.initiate_connection(
21 app_name=app,
22 use_composio_auth=False,
23 force_new_integration=True,
24 connected_account_params=connection_params,
25 auth_mode=auth_mode,
26 redirect_url=redirect_url,
27 )
28 return connection
29
30connection_params_info = request_connection_params(integration_id)
31connection_params = get_connection_values(
32 connection_params_info["expected_params"]
33)
34connection = initiate_connection(user_id, app, connection_params, "BEARER_TOKEN")

Examples

OAuth 2.0 applications generally don’t have any expected_params since the OAuth flow is supposed to capture and store the relevant credentials.

1from composio_openai import App, ComposioToolSet
2
3
4toolset = ComposioToolSet()
5entity = toolset.get_entity("default")
6github_params = toolset.get_expected_params_for_user(app=App.GITHUB)
7# []
8
9github_connection_request = entity.initiate_connection(
10 app_name=App.GITHUB,
11 auth_mode=github_params["auth_scheme"],
12 auth_config={},
13)
14print(github_connection_request.model_dump_json(indent=2))

Once the connection object has been created, the redirectUrl has to be emitted back to the user so that they can follow the OAuth credentials.

Connection Request Object
1{
2 "connectionStatus": "INITIATED",
3 "connectedAccountId": "ec33a9e2-75e1-4e01-9c7a-60a1481e4d8e",
4 "redirectUrl": "https://backend.composio.dev/s/9eNG2Svq"
5}
The redirectUrl in the connection object is the URL that initiates the OAuth flow, guiding the user to the authentication page. In contrast, the redirectUrl specified as an argument when initiating the connection determines where the user will be redirected after completing the OAuth process.

Many applications that have OAuth 2.0, also support the user providing their own Bearer token.

1from composio_openai import App, ComposioToolSet
2
3
4toolset = ComposioToolSet()
5entity = toolset.get_entity("default")
6gmail_params = toolset.get_expected_params_for_user(app=App.GMAIL, auth_scheme="BEARER_TOKEN")
7print(gmail_params["expected_params"])
8# [ExpectedFieldInput(name='token', type='string', description='Token for bearer token auth', displayName='Token', is_secret=False, required=True, expected_from_customer=True, default=None, get_current_user_endpoint=None)]
9
10
11gmail_connection_request = entity.initiate_connection(
12 app_name=App.GMAIL,
13 auth_mode=gmail_params["auth_scheme"],
14 auth_config={"token": "gmail_token"},
15)
16
17print(gmail_connection_request.model_dump_json(indent=2))
Connection Request Object
1{
2 "connectionStatus": "ACTIVE",
3 "connectedAccountId": "3362dc81-4313-4564-927e-571e4ff51b95",
4 "redirectUrl": null
5}

You can ask the user’s to enter in their API key for apps and services that support it. Composio will store the key securely.

1from composio_openai import App, ComposioToolSet
2
3toolset = ComposioToolSet()
4entity = toolset.get_entity("default")
5
6notion_params = toolset.get_expected_params_for_user(app=App.NOTION)
7notion_params["expected_params"]
8print(notion_params["expected_params"])
9# [ExpectedFieldInput(name='api_key', type='string', description='Your notion API key for authentication. Obtain it from your notion settings.', displayName='API Key', is_secret=False, required=True, expected_from_customer=True, default=None, get_current_user_endpoint=None)]
10
11notion_connection_request = entity.initiate_connection(
12 app_name=App.NOTION,
13 auth_mode=notion_params["auth_scheme"],
14 auth_config={"token": "notion_token"},
15)
Connnection request object
1{
2 "connectionStatus": "ACTIVE",
3 "connectedAccountId": "da821894-2383-4f75-8590-ebbc242a4129",
4 "redirectUrl": null
5}