Connecting to OAuth Apps

Handle the user connection flow for apps like Google, GitHub, Slack

This guide details the programmatic steps required to connect your users (Entities) to external applications that use OAuth 2.0 for authorization (e.g., Google Workspace, GitHub, Slack, Salesforce).

This flow involves redirecting the user to the external service’s login and consent screen in their browser.

Prerequisites:

  • An Integration for the OAuth app must be configured in Composio, providing you with an integration_id. Ensure it’s set up correctly for OAuth (using Composio’s shared app or your own credentials).
  • A unique entity_id representing the user within your application.

OAuth Connection Flow

The process involves initiating the connection, redirecting the user for authorization, and then waiting for Composio to confirm the connection is active.

Step 1: Initiate the Connection

Use the initiate_connection (Python) or initiateConnection (TypeScript) method on the user’s Entity object. Provide the integration_id for the OAuth app you configured.

1from composio_openai import ComposioToolSet, App
2
3# Assumes toolset is initialized
4toolset = ComposioToolSet()
5user_id = "your_user_unique_id"
6# Get this from your Composio Integration setup
7google_integration_id = "int_google_xxxxxxxx..."
8
9entity = toolset.get_entity(id=user_id)
10
11try:
12 print(f"Initiating OAuth connection for entity {entity.id}...")
13 connection_request = toolset.initiate_connection(
14 integration_id=google_integration_id,
15 entity_id=user_id,
16 # Optionally add: redirect_url="https://yourapp.com/final-destination"
17 # if you want user sent somewhere specific *after* Composio finishes.
18 # Optional add: app=App.APP_NAME
19 )
20
21 # Check if a redirect URL was provided (expected for OAuth)
22 if connection_request.redirectUrl:
23 print(f"Received redirect URL: {connection_request.redirectUrl}")
24 else:
25 print("Error: Expected a redirectUrl for OAuth flow but didn't receive one.")
26 # Handle error: Maybe the integration is misconfigured?
27
28 # Store connection_request.connectedAccountId if needed for Step 3 polling
29 # connection_id_in_progress = connection_request.connectedAccountId
30
31except Exception as e:
32 print(f"Error initiating connection: {e}")

The key output here is the redirectUrl.

Step 2: Redirect the User

Your application must now direct the user’s browser to the redirectUrl obtained in Step 1.

  • How: This typically involves sending an HTTP 302 Redirect response from your backend, or using window.location.href = redirectUrl; in your frontend JavaScript.

The user will see the external service’s login page (if not already logged in) followed by an authorization screen asking them to grant the permissions (scopes) defined in your Composio Integration.

Step 3: Wait for Connection Activation

After the user authorizes the app, the external service redirects back (typically to Composio’s callback URL). Composio exchanges the authorization code for access/refresh tokens and securely stores them, marking the Connection as ACTIVE.

Your application needs to wait for this confirmation. Use the wait_until_active (Python) / waitUntilActive (TypeScript) method on the connection_request object obtained in Step 1.

1# Assuming 'connection_request' from Step 1
2
3print("Waiting for user authorization and connection activation...")
4try:
5 # Poll Composio until the status is ACTIVE
6 active_connection = connection_request.wait_until_active(
7 client=toolset.client, # Pass the Composio client instance
8 timeout=180 # Wait up to 3 minutes (adjust as needed)
9 )
10 print(f"Success! Connection is ACTIVE. ID: {active_connection.id}")
11 # Store active_connection.id associated with your user (entity_id)
12 # Now ready for Step 4.
13except Exception as e: # Catches TimeoutError, etc.
14 print(f"Connection did not become active within timeout or failed: {e}")
15 # Implement retry logic or inform the user

Step 4: Use the Connection

Once wait_until_active completes successfully, the Connection is ready. You can now use the entity_id or the obtained active_connection.id to execute actions on behalf of this user for the connected app.

Step 5 (Optional): Refresh the Connection

Sometimes, a user’s connection to an external service might become invalid. This can happen if:

  • The access token expires (though Composio handles automatic refresh for many OAuth 2.0 flows).
  • The user revokes access permissions directly on the third-party service.

You may see errors like:

Composio SDK while executing action 'GMAIL_FETCH_EMAILS':
{"status":400,"message":"Connected account is disabled","requestId":"000000000000","type":"BadRequestError","details":{}}

When a connection is invalid you need to guide the user through the authentication process again to re-establish a valid connection.

🚧 We don’t currently support the ability to re-initiate connections using our Python SDK. You may use the v1/connections/reinitiate-connection endpoint.
1# Create the connection using the same parameters.
2user_id = "alice"
3entity = toolset.get_entity(user_id)
4connection_req = entity.initiate_connection(
5 app_name=App.GMAIL,
6 entity_id=user_id,
7 # You can use integration_id as well
8 # integration_id=GMAIL_INTEGRATION_ID,
9 # Add redirect_url if needed for your app flow
10 # redirect_url="https://yourapp.com/post-auth"
11)
12
13print(f"Please re-authenticate your Gmail account: {connection_req.redirectUrl}")
14print(f"Initial status: {connection_req.connectionStatus}") # Will likely be INITIATED