# OAuth
URL: https://metorial.com/docs/build/sdk/oauth

Handle user authorization for OAuth-enabled providers using Provider Setup Sessions

---

<PageIntro>
  <Learn>
    * How OAuth works with Metorial
    * Creating Provider Setup Sessions
    * Storing and reusing Provider Auth Configs
  </Learn>

  <Reading title="External resources">
    * [OAuth integrations](/docs/platform/integrations/oauth)
  </Reading>
</PageIntro>

OAuth lets your users authorize access to their accounts on services like Slack, GitHub, Google Calendar, and more. This enables your AI agents to perform actions on behalf of your users with their explicit permission.

## How OAuth works [#how-oauth-works]

The OAuth flow uses **Provider Setup Sessions**:

1. **Create a Provider Setup Session** for the provider the user needs to authorize
2. **Redirect the user** to the session URL to complete OAuth in their browser
3. **Wait for completion** — returns the completed setup session with an auth config
4. **Store the Provider Auth Config ID** for that user in your database
5. **Pass the auth config ID** when creating sessions for that user

## Creating provider setup sessions [#creating-provider-setup-sessions]

<CodeBlockTabs defaultValue="TypeScript" mode="code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="TypeScript">
      TypeScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Python">
      Python
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="TypeScript">
    ```typescript
    let setupSession = await metorial.providerDeployments.setupSessions.create({
        providerId: 'your-provider-id',
        providerAuthMethodId: 'oauth',

        // Optional: specify deployment if you have multiple for the same provider
        // providerDeploymentId: 'your-deployment-id',

        // Optional: redirect user here after authorizing
        // callbackUri: 'https://yourapp.com/oauth/callback'
    });

    // Redirect your user to this URL
    console.log('Authorize here:', setupSession.url);
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Python">
    ```python
    setup_session = await metorial.providers.setup_sessions.create(
        provider_id="your-provider-id",
        provider_auth_method_id="oauth",

        # Optional: specify deployment if you have multiple for the same provider
        # provider_deployment_id="your-deployment-id",

        # Optional: redirect user here after authorizing
        # redirect_url="https://yourapp.com/oauth/callback"
    )

    # Redirect your user to this URL
    print(f"Authorize here: {setup_session.url}")
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Waiting for completion [#waiting-for-completion]

<CodeBlockTabs defaultValue="TypeScript" mode="code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="TypeScript">
      TypeScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Python">
      Python
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="TypeScript">
    ```typescript
    // Waits until the user completes OAuth — returns the completed setup sessions
    let completed = await metorial.providerDeployments.setupSessions.waitForCompletion([setupSession]);

    // Store the auth config ID for this user
    await db.users.update(userId, {
        slackAuthConfigId: completed[0]!.authConfig!.id
    });
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Python">
    ```python
    # Waits until the user completes OAuth — returns the completed setup session
    completed = await metorial.wait_for_setup_session([setup_session])

    # Store the auth config ID for this user
    await db.users.update(user_id, slack_auth_config_id=completed[0].auth_config.id)
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Using auth configs in sessions [#using-auth-configs-in-sessions]

Retrieve the stored auth config ID from your database and pass it when creating a session:

<CodeBlockTabs defaultValue="TypeScript" mode="code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="TypeScript">
      TypeScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Python">
      Python
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="TypeScript">
    ```typescript
    let session = await metorial.connect({
      adapter: metorialAnthropic(),
      providers: [
        {
    		providerDeploymentId: 'your-provider-deployment-id',
    		providerAuthConfigId: storedAuthConfig
    	}
      ]
    });
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Python">
    ```python
    session = await metorial.connect(
        adapter=metorial_anthropic(),
        providers=[
            {
                "provider_deployment_id": "slack-deployment-id",
                "provider_auth_config_id": stored_auth_config_id  # From your database
            }
        ],
    )
    tools = session.tools()
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Multiple OAuth services [#multiple-oauth-services]

You can combine multiple OAuth-enabled providers in a single session:

<CodeBlockTabs defaultValue="TypeScript" mode="code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="TypeScript">
      TypeScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Python">
      Python
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="TypeScript">
    ```typescript
    providers: [
      {
        providerDeploymentId: "github-deployment-id",
        providerAuthConfigId: githubAuthConfigId,
      },
      {
        providerDeploymentId: "slack-deployment-id",
        providerAuthConfigId: slackAuthConfigId,
      },
      {
        providerDeploymentId: "exa-deployment-id", // No OAuth needed
      },
    ]
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Python">
    ```python
    session = await metorial.connect(
        adapter=metorial_openai(),
        providers=[
            {
                "provider_deployment_id": "github-deployment-id",
                "provider_auth_config_id": github_auth_config_id
            },
            {
                "provider_deployment_id": "slack-deployment-id",
                "provider_auth_config_id": slack_auth_config_id
            },
            {
                "provider_deployment_id": "exa-deployment-id"  # No OAuth needed
            }
        ],
    )
    tools = session.tools()
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Complete example [#complete-example]

<CodeBlockTabs defaultValue="TypeScript" mode="code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="TypeScript">
      TypeScript
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Python">
      Python
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="TypeScript">
    ```typescript
    import { Metorial } from 'metorial';
    import { metorialAnthropic } from '@metorial/anthropic';

    let metorial = new Metorial({ apiKey: process.env.METORIAL_API_KEY });

    // 1. Create setup session
    let setupSession = await metorial.providerDeployments.setupSessions.create({
        providerId: 'your-slack-provider-id',
        providerAuthMethodId: 'oauth',
        callbackUri: 'https://yourapp.com/oauth/callback'
    });

    // 2. Send URL to user
    console.log('Please authorize:', setupSession.url);

    // 3. Wait for completion
    let completed = await metorial.providerDeployments.setupSessions.waitForCompletion([setupSession]);

    // 4. Store auth config ID for this user
    // database.save(userId, completed[0].authConfig.id)

    // 5. Use in a session
    let session = await metorial.connect({
      adapter: metorialAnthropic(),
      providers: [
        {
    		providerDeploymentId: 'your-slack-provider-id',
    		providerAuthConfigId: completed[0]!.authConfig!.id
    	}
      ]
    });
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Python">
    ```python
    import asyncio
    from metorial import Metorial, metorial_anthropic

    async def main():
        metorial = Metorial(api_key="your-metorial-api-key")

        # 1. Create setup session
        setup_session = await metorial.providers.setup_sessions.create(
            provider_id="your-slack-provider-id",
            provider_auth_method_id="oauth",
            redirect_url="https://yourapp.com/oauth/callback"
        )

        # 2. Send URL to user
        print(f"Please authorize: {setup_session.url}")

        # 3. Wait for completion
        completed = await metorial.wait_for_setup_session([setup_session])

        # 4. Store auth config ID for this user
        # database.save(user_id, completed[0].auth_config.id)

        # 5. Use in a session
        session = await metorial.connect(
            adapter=metorial_anthropic(),
            providers=[
                {
                    "provider_deployment_id": "your-slack-deployment-id",
                    "provider_auth_config_id": completed[0].auth_config.id
                }
            ],
        )
        # Your AI now has access to user's Slack via session.tools()

    asyncio.run(main())
    ```
  </CodeBlockTab>
</CodeBlockTabs>