---
title: Choose User IDs Carefully for Security and Isolation
impact: CRITICAL
description: Use proper user IDs to ensure data isolation, security, and correct session management
tags: [tool-router, user-id, security, authentication, multi-tenant]
---

# Choose User IDs Carefully for Security and Isolation

User IDs are the **foundation of Composio's data isolation**. They determine which user's connections, data, and permissions are used for tool execution. Choose them carefully to ensure security and proper data isolation.

## ❌ Incorrect

```typescript
// DON'T: Use 'default' in production multi-user apps
async function handleUserRequest(req: Request) {
  const session = await composio.create('default', {
    toolkits: ['gmail', 'slack']
  });

  // ❌ All users share the same session
  // ❌ No data isolation
  // ❌ Security nightmare
  // ❌ User A can access User B's emails!
}
```

```python
# DON'T: Use 'default' in production multi-user apps
async def handle_user_request(req):
    session = composio.create(
        user_id="default",
        toolkits=["gmail", "slack"]
    )

    # ❌ All users share the same session
    # ❌ No data isolation
    # ❌ Security nightmare
    # ❌ User A can access User B's emails!
```

```typescript
// DON'T: Use email addresses as user IDs
async function handleUserRequest(req: Request) {
  const session = await composio.create(req.user.email, {
    toolkits: ['github']
  });

  // ❌ Emails can change
  // ❌ Breaks session continuity
  // ❌ Historical data loss
}
```

## ✅ Correct - Use Database User IDs

```typescript
// DO: Use your database user ID (UUID, primary key, etc.)
import { Composio } from '@composio/core';
import { VercelProvider } from '@composio/vercel';

const composio = new Composio({
  provider: new VercelProvider()
});

async function handleUserRequest(req: Request) {
  // Get user ID from your auth system
  const userId = req.user.id; // e.g., "550e8400-e29b-41d4-a716-446655440000"

  // Create isolated session for this user
  const session = await composio.create(userId, {
    toolkits: ['gmail', 'slack']
  });

  const tools = await session.tools();

  // ✅ Each user gets their own session
  // ✅ Complete data isolation
  // ✅ User A cannot access User B's data
  // ✅ Connections tied to correct user
  return await agent.run(req.message, tools);
}
```

```python
# DO: Use your database user ID (UUID, primary key, etc.)
from composio import Composio
from composio_openai import OpenAIProvider

composio = Composio(provider=OpenAIProvider())

async def handle_user_request(req):
    # Get user ID from your auth system
    user_id = req.user.id  # e.g., "550e8400-e29b-41d4-a716-446655440000"

    # Create isolated session for this user
    session = composio.create(
        user_id=user_id,
        toolkits=["gmail", "slack"]
    )

    tools = session.tools()

    # ✅ Each user gets their own session
    # ✅ Complete data isolation
    # ✅ User A cannot access User B's data
    # ✅ Connections tied to correct user
    return await agent.run(req.message, tools)
```

## ✅ Correct - Use Auth Provider IDs

```typescript
// DO: Use IDs from your auth provider
import { Composio } from '@composio/core';
import { VercelProvider } from '@composio/vercel';

const composio = new Composio({
  provider: new VercelProvider()
});

async function handleClerkUser(userId: string) {
  // Using Clerk user ID
  // e.g., "user_2abc123def456"
  const session = await composio.create(userId, {
    toolkits: ['github']
  });

  return session;
}

async function handleAuth0User(userId: string) {
  // Using Auth0 user ID
  // e.g., "auth0|507f1f77bcf86cd799439011"
  const session = await composio.create(userId, {
    toolkits: ['gmail']
  });

  return session;
}

async function handleSupabaseUser(userId: string) {
  // Using Supabase user UUID
  // e.g., "d7f8b0c1-1234-5678-9abc-def012345678"
  const session = await composio.create(userId, {
    toolkits: ['slack']
  });

  return session;
}
```

```python
# DO: Use IDs from your auth provider
from composio import Composio
from composio_openai import OpenAIProvider

composio = Composio(provider=OpenAIProvider())

async def handle_clerk_user(user_id: str):
    # Using Clerk user ID
    # e.g., "user_2abc123def456"
    session = composio.create(
        user_id=user_id,
        toolkits=["github"]
    )
    return session

async def handle_auth0_user(user_id: str):
    # Using Auth0 user ID
    # e.g., "auth0|507f1f77bcf86cd799439011"
    session = composio.create(
        user_id=user_id,
        toolkits=["gmail"]
    )
    return session

async def handle_supabase_user(user_id: str):
    # Using Supabase user UUID
    # e.g., "d7f8b0c1-1234-5678-9abc-def012345678"
    session = composio.create(
        user_id=user_id,
        toolkits=["slack"]
    )
    return session
```

## ✅ Correct - Organization-Level Applications

```typescript
// DO: Use organization ID for org-level apps
import { Composio } from '@composio/core';
import { VercelProvider } from '@composio/vercel';

const composio = new Composio({
  provider: new VercelProvider()
});

// When apps are connected at organization level (not individual users)
async function handleOrgLevelApp(req: Request) {
  // Use organization ID, NOT individual user ID
  const organizationId = req.user.organizationId;

  const session = await composio.create(organizationId, {
    toolkits: ['slack', 'github'], // Org-wide tools
    manageConnections: true
  });

  // All users in the organization share these connections
  // Perfect for team collaboration tools
  const tools = await session.tools();
  return await agent.run(req.message, tools);
}

// Example: Slack workspace integration
async function createWorkspaceSession(workspaceId: string) {
  // Workspace ID as user ID
  const session = await composio.create(`workspace_${workspaceId}`, {
    toolkits: ['slack', 'notion', 'linear']
  });

  return session;
}
```

```python
# DO: Use organization ID for org-level apps
from composio import Composio
from composio_openai import OpenAIProvider

composio = Composio(provider=OpenAIProvider())

# When apps are connected at organization level (not individual users)
async def handle_org_level_app(req):
    # Use organization ID, NOT individual user ID
    organization_id = req.user.organization_id

    session = composio.create(
        user_id=organization_id,
        toolkits=["slack", "github"],  # Org-wide tools
        manage_connections=True
    )

    # All users in the organization share these connections
    # Perfect for team collaboration tools
    tools = session.tools()
    return await agent.run(req.message, tools)

# Example: Slack workspace integration
async def create_workspace_session(workspace_id: str):
    # Workspace ID as user ID
    session = composio.create(
        user_id=f"workspace_{workspace_id}",
        toolkits=["slack", "notion", "linear"]
    )
    return session
```

## When to Use 'default'

The `'default'` user ID should **ONLY** be used in these scenarios:

### ✅ Development and Testing
```typescript
// Testing locally
const session = await composio.create('default', {
  toolkits: ['gmail']
});
```

### ✅ Single-User Applications
```typescript
// Personal automation script
// Only YOU use this app
const session = await composio.create('default', {
  toolkits: ['github', 'notion']
});
```

### ✅ Demos and Prototypes
```typescript
// Quick demo for investors
const session = await composio.create('default', {
  toolkits: ['hackernews']
});
```

### ❌ NEVER in Production Multi-User Apps
```typescript
// Production API serving multiple users
// ❌ DON'T DO THIS
const session = await composio.create('default', {
  toolkits: ['gmail']
});
```

## User ID Best Practices

### 1. **Use Stable, Immutable Identifiers**

✅ **Good:**
- Database primary keys (UUIDs)
- Auth provider user IDs
- Immutable user identifiers

❌ **Bad:**
- Email addresses (can change)
- Usernames (can be modified)
- Phone numbers (can change)

```typescript
// ✅ Good: Stable UUID
const userId = user.id; // "550e8400-e29b-41d4-a716-446655440000"

// ❌ Bad: Email (mutable)
const userId = user.email; // "john@example.com" -> changes to "john@newdomain.com"

// ❌ Bad: Username (mutable)
const userId = user.username; // "john_doe" -> changes to "john_smith"
```

### 2. **Ensure Uniqueness**

```typescript
// ✅ Good: Guaranteed unique
const userId = database.users.findById(id).id;

// ✅ Good: Auth provider guarantees uniqueness
const userId = auth0.user.sub; // "auth0|507f1f77bcf86cd799439011"

// ❌ Bad: Not guaranteed unique
const userId = user.firstName; // Multiple "John"s exist
```

### 3. **Match Your Authentication System**

```typescript
// Express.js with Passport
app.post('/api/agent', authenticateUser, async (req, res) => {
  const userId = req.user.id; // From Passport
  const session = await composio.create(userId, config);
});

// Next.js with Clerk
export async function POST(req: NextRequest) {
  const { userId } = auth(); // From Clerk
  const session = await composio.create(userId!, config);
}

// FastAPI with Auth0
@app.post("/api/agent")
async def agent_endpoint(user: User = Depends(get_current_user)):
    user_id = user.id  # From Auth0
    session = composio.create(user_id=user_id, **config)
```

### 4. **Namespace for Multi-Tenancy**

```typescript
// When you have multiple applications/workspaces per user
const userId = `app_${appId}_user_${user.id}`;
// e.g., "app_saas123_user_550e8400"

const session = await composio.create(userId, {
  toolkits: ['gmail']
});

// Each app instance gets isolated connections
```

### 5. **Be Consistent Across Your Application**

```typescript
// ✅ Good: Same user ID everywhere
async function handleRequest(req: Request) {
  const userId = req.user.id;

  // Use same ID for sessions
  const session = await composio.create(userId, config);

  // Use same ID for direct tool execution
  await composio.tools.execute('GMAIL_SEND_EMAIL', {
    userId: userId,
    arguments: { to: 'user@example.com', subject: 'Test' }
  });

  // Use same ID for connected accounts
  await composio.connectedAccounts.get(userId, 'gmail');
}
```

## Security Implications

### ⚠️ User ID Leakage
```typescript
// ❌ DON'T: Expose user IDs to client
app.get('/api/session', (req, res) => {
  res.json({
    sessionId: session.sessionId,
    userId: req.user.id // ❌ Sensitive information
  });
});

// ✅ DO: Keep user IDs server-side only
app.get('/api/session', (req, res) => {
  res.json({
    sessionId: session.sessionId
    // Don't send userId to client
  });
});
```

### ⚠️ User ID Validation
```typescript
// ✅ Always validate user IDs match authenticated user
app.post('/api/agent/:userId', authenticateUser, async (req, res) => {
  const requestedUserId = req.params.userId;
  const authenticatedUserId = req.user.id;

  // Validate user can only access their own data
  if (requestedUserId !== authenticatedUserId) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  const session = await composio.create(authenticatedUserId, config);
});
```

## Common Patterns

### Pattern 1: User-Level Isolation (Most Common)
```typescript
// Each user has their own connections
// Use user ID from your database/auth system
const session = await composio.create(req.user.id, {
  toolkits: ['gmail', 'github']
});
```

### Pattern 2: Organization-Level Sharing
```typescript
// All org members share connections
// Use organization ID
const session = await composio.create(req.user.organizationId, {
  toolkits: ['slack', 'notion']
});
```

### Pattern 3: Hybrid (User + Org)
```typescript
// Personal tools use user ID
const personalSession = await composio.create(req.user.id, {
  toolkits: ['gmail'] // Personal Gmail
});

// Team tools use org ID
const teamSession = await composio.create(req.user.organizationId, {
  toolkits: ['slack', 'jira'] // Team Slack/Jira
});
```

## Key Principles

1. **Never use 'default' in production multi-user apps**
2. **Use stable, immutable identifiers** (UUIDs, not emails)
3. **Match your authentication system's user IDs**
4. **Validate user IDs server-side** for security
5. **Be consistent** across sessions and direct tool usage
6. **Use org IDs** for organization-level applications
7. **Namespace when needed** for multi-tenancy

## Reference

- [Composio Sessions](https://docs.composio.dev/sdk/typescript/api/tool-router#creating-sessions)
- [User ID Security](https://docs.composio.dev/sdk/typescript/core-concepts#user-ids)
- [Connected Accounts](https://docs.composio.dev/sdk/typescript/api/connected-accounts)
