OAuth callback identity verification
OAuth callback identity verification is an opt-in, per-project control that adds a check between the OAuth provider's redirect and the activation of a connected account. Before Composio finalizes the connection, your own server confirms which of your users is completing the flow.
It is off by default. Existing projects and connections are unaffected until you enable it.
Why you might want it
When a user authorizes a toolkit, the OAuth provider redirects back to Composio with an authorization code. That code proves the user approved access, but it does not prove which of your users is holding the browser at that moment. If a callback is intercepted or replayed, a connection could be bound to the wrong user.
Identity verification closes that gap. Composio pauses activation and asks your server — which already knows who is signed in — to assert the user. The connection activates only when your assertion matches the user the connection was initiated for.
How it works
- A user starts an OAuth connection as usual, initiated with your
user_id. - The user authorizes with the provider, which redirects back to Composio.
- Instead of activating the connection, Composio redirects the user's browser to your verifier URL with a single-use
session_uriquery parameter — and no other identifiers. - Your server identifies the signed-in user, then calls
POST /api/v3.1/connected_accounts/complete_authwith thesession_uriand that user'suser_id. - Composio confirms the
user_idmatches the connection owner, completes the token exchange, and returns the now-active connected account.
The session_uri deliberately carries no user or connection identifier. Your server is expected to derive the user from its own authenticated session — that independent assertion is the verification.
Enabling verification
Verification is configured per project and is off by default. Enabling it sets a verifier URL for the project: the page Composio redirects users to after the provider returns.
Once verification is enabled for a project, connections must be initiated with a real user_id. A connection started for the default user cannot be verified and is rejected at initiation, because there is no specific identity to confirm.
Enabling verification does not change how connections are initiated — only how they are completed. Connections created before you enabled it, and any created while it is off, continue to activate directly.
Completing a verification
When your verifier URL receives a request with a session_uri, identify the signed-in user and call complete_auth from your server with your project API key.
curl -X POST "https://backend.composio.dev/api/v3.1/connected_accounts/complete_auth" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"session_uri": "session_xxx",
"user_id": "user_123"
}'Response:
{
"connected_account": {
"id": "ca_your-connected-account-id",
"user_id": "user_123",
"status": "ACTIVE",
"toolkit": { "slug": "github" },
"auth_config": {
"id": "ac_your-auth-config-id",
"auth_scheme": "OAUTH2",
"is_composio_managed": true
}
}
}The response is the full connected account, now ACTIVE.
Responses to handle
400— theuser_iddoes not match the user the connection was initiated for. The connection stays inactive.404— thesession_uriis unknown, expired, or already used. Sessions are single-use and short-lived, so a retried or shared link resolves here; the user restarts the connection.200— verification succeeded and the connection is active.
Identifying the user at your verifier
Because Composio passes only the session_uri, your verifier page must be able to identify the user itself. In practice this means the browser that completes the OAuth flow carries an authenticated session with your application, so your server can map the request to the correct user_id.
Design your flow so the OAuth link is opened in a context your application can authenticate. If a user opens the link somewhere you cannot identify them, your server has no user_id to assert and the connection cannot be completed.
Next
- White-labeling authentication — route the OAuth callback through your own domain and redirect users after authentication.
- Manually authenticating users — initiate connections and check their status outside of chat.