Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e88e05e
feat(slack): add support for custom bot configuration and enhance doc…
yuriassuncx Sep 25, 2025
adad532
feat(slack): enhance custom bot name handling and re-authentication b…
yuriassuncx Sep 25, 2025
133fa85
feat(slack): update bot identifier handling in invoke and join actions
yuriassuncx Sep 25, 2025
bdff555
Merge branch 'feat/slack-custom-bot' of https://github.com/yuriassunc…
yuriassuncx Oct 1, 2025
591c19c
Merge branch 'main' of https://github.com/yuriassuncx/apps-mcp into f…
yuriassuncx Oct 1, 2025
80ebc4e
feat(slack): implement custom bot selection interface and enhance OAu…
yuriassuncx Oct 1, 2025
ac14e65
feat(slack): refactor state decoding logic for custom bot handling
yuriassuncx Oct 1, 2025
4c13866
feat(slack): implement secure custom bot credential handling and sess…
yuriassuncx Oct 1, 2025
16ecb57
fix: guard against missing WebCrypto in Node 18 environments
yuriassuncx Oct 1, 2025
5ccac83
fix: update slack README.md
yuriassuncx Oct 1, 2025
c73b5cc
feat: validate returnUrl before constructing redirect
yuriassuncx Oct 1, 2025
f273238
fix: update README.md flow diagram formatting and improve session tok…
yuriassuncx Oct 1, 2025
3bc9dd8
Refactor Slack OAuth flow: remove store-credentials action, enhance s…
yuriassuncx Oct 2, 2025
4708798
Merge branch 'feat/slack-custom-bot' of https://github.com/yuriassunc…
yuriassuncx Oct 2, 2025
be948dc
fix: sanitize current URL in bot selection page to prevent XSS attacks
yuriassuncx Oct 2, 2025
90f46c0
feat: add debug mode configuration for Slack bot integration
yuriassuncx Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 239 additions & 20 deletions slack/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
# Slack OAuth App

A Deco app for integrating with Slack using OAuth 2.0 authentication. This app allows you to send messages, interact with channels, and manage Slack workspaces through a secure OAuth flow.
A Deco app for integrating with Slack using OAuth 2.0 authentication. This app allows you to send messages, interact with channels, and manage Slack workspaces through a secure OAuth flow with flexible bot configuration options.

## Features

- πŸ” **OAuth 2.0 Authentication** - Secure token-based authentication
- πŸ€– **Flexible Bot Configuration** - Choose between deco.chat bot or custom Slack apps
- πŸ’¬ **Message Management** - Send messages and replies to channels
- πŸ“‹ **Channel Operations** - List and interact with workspace channels
- πŸ‘₯ **User Management** - Get user information and profiles
- 🎯 **Reactions** - Add emoji reactions to messages
- οΏ½ **File Upload V2** - Upload files using the new Slack API (files.upload sunset Nov 12, 2025)
- οΏ½πŸ”„ **Automatic Token Refresh** - Handles token expiration automatically
- πŸ“ **File Upload V2** - Upload files using the new Slack API (files.upload sunset Nov 12, 2025)
- πŸ”„ **Automatic Token Refresh** - Handles token expiration automatically
- 🎨 **Custom Bot Selection UI** - Interactive interface for choosing integration type

## Integration Options

### 1. deco.chat Bot (Recommended)

Use the official deco.chat bot for seamless integration:

- βœ… **Pre-configured** - All necessary permissions included
- βœ… **Zero setup** - No Slack app creation required
- βœ… **Maintained by Deco** - Automatic updates and security patches
- βœ… **Best for most users** - Quick setup and reliable operation

### 2. Custom Bot

Configure your own Slack app for advanced use cases:

- 🎯 **Full control** - Use your own Slack app credentials
- 🎨 **Custom branding** - Customize bot name and appearance
- πŸ”’ **Enterprise ready** - Full control over permissions and scopes
- 🏒 **Private deployments** - Use your own Slack app infrastructure

## ⚠️ IMPORTANT: File Upload API Migration

Expand All @@ -24,14 +46,23 @@ A Deco app for integrating with Slack using OAuth 2.0 authentication. This app a

## Setup Instructions

### 1. Create a Slack App
### Option 1: Using deco.chat Bot (Recommended)

1. **Start OAuth Flow** - No preliminary setup needed
2. **Select Integration Type** - Choose "deco.chat Bot" in the selection interface
3. **Authorize** - Complete OAuth authorization in your Slack workspace
4. **Ready to use** - Integration is immediately available

### Option 2: Setting Up Custom Bot

#### Step 1: Create a Slack App

1. Go to [api.slack.com/apps](https://api.slack.com/apps)
2. Click "Create New App" β†’ "From scratch"
3. Enter your app name and select a workspace
4. Navigate to "OAuth & Permissions" in the sidebar

### 2. Configure OAuth Settings
#### Step 2: Configure OAuth Settings

1. Add your redirect URL under "Redirect URLs":
- Development: `https://your-dev-domain.com/oauth/callback`
Expand All @@ -45,31 +76,185 @@ A Deco app for integrating with Slack using OAuth 2.0 authentication. This app a
- `users:read` - View people in the workspace
- `users:read.email` - View email addresses of people in the workspace

### 3. Environment Variables
#### Step 3: Use Custom Bot in OAuth Flow

1. **Start OAuth Flow** - Begin the standard OAuth process
2. **Select Integration Type** - Choose "Custom Bot" in the selection interface
3. **Enter Credentials**:
- **Client ID**: Your Slack app's Client ID
- **Client Secret**: Your Slack app's Client Secret
- **Bot Name** (optional): Custom identifier for your bot
4. **Complete Authorization** - Finish OAuth flow with your custom app

## Bot Selection Interface

The app now features an interactive selection interface that appears during OAuth flow:

### Selection Options

- **deco.chat Bot**: Official bot with pre-configured settings
- **Custom Bot**: Your own Slack app with custom configuration

Set the following environment variables:
### Custom Bot Configuration

When selecting "Custom Bot", you'll need to provide:

- **Client ID** (required): From your Slack app's "Basic Information" page
- **Client Secret** (required): From your Slack app's "Basic Information" page
- **Bot Name** (optional): Custom identifier for branding purposes

### Interface Features

- 🎨 **Dark/Light theme** toggle
- πŸ“± **Responsive design** for mobile and desktop
- ✨ **Interactive selection** with visual feedback
- πŸ”’ **Secure credential handling** with masked secrets

## OAuth Flow

The app provides these endpoints for OAuth:

- **Start OAuth**: `/loaders/oauth/start` - Shows selection interface or redirects to Slack
- **OAuth Callback**: `/actions/oauth/callback` - Handles authorization response and token exchange

### Flow Diagram

```
User β†’ Start OAuth β†’ Selection UI β†’ [Choose Option] β†’ Slack Authorization β†’ Callback β†’ Complete
↓ ↓
[deco.chat bot] [Custom bot + credentials]
```

## Environment Variables

For custom bot configurations, you may optionally set:

```bash
SLACK_CLIENT_ID=your_slack_client_id
SLACK_CLIENT_SECRET=your_slack_client_secret
SLACK_CLIENT_ID=your_slack_client_id # Optional: Default custom bot
SLACK_CLIENT_SECRET=your_slack_client_secret # Optional: Default custom bot
```

## API Methods

### Channels
- `getChannels(teamId, limit?, cursor?)` - List workspace channels
- `getChannelHistory(channelId, limit?)` - Get channel message history

### Messages
- `postMessage(channelId, text)` - Send a message to a channel
- `postReply(channelId, threadTs, text)` - Reply to a thread
- `getThreadReplies(channelId, threadTs)` - Get thread replies

### Users
- `getUsers(teamId, limit?, cursor?)` - List workspace users
- `getUserProfile(userId)` - Get user profile information

### Reactions
- `addReaction(channelId, timestamp, reaction)` - Add emoji reaction

### File Upload
- `uploadFileV2(options)` - Upload files using new V2 API (recommended)
- `uploadFile(options)` - Upload files using legacy API (deprecated, shows warning)

**New V2 Upload Example:**
```typescript
const response = await slack.uploadFileV2({
channels: "C1234567890", // Optional
file: fileBlob, // Supports Uint8Array, Blob, File, base64, data URL
filename: "document.pdf",
title: "Important Document",
thread_ts: "1234567890.123456", // Optional - upload to thread
initial_comment: "Here's the document"
});
```

You can find these values in your Slack app's "Basic Information" page under "App Credentials".
## Custom Bot Configuration Details

### Bot Name Usage

The bot name is used in:
- Channel welcome messages: `"To interact with me, just mention @your-bot-name in your messages!"`
- Channel listings: Shows `@your-bot-name` instead of `@deco.chat`
- App configuration: Stored as `customBotName` for future reference

### Bot Name Preservation

### 4. OAuth Flow
During re-authentication or token refresh:
- **With botName parameter**: Updates to the new custom name
- **Without botName parameter**: Preserves the existing custom bot name
- **First install**: Uses "deco.chat" as default if no botName provided

The app provides two endpoints for OAuth:
### Multiple Bot Support

- **Start OAuth**: `/loaders/oauth/start` - Redirects users to Slack for authorization
- **OAuth Callback**: `/actions/oauth/callback` - Handles the authorization response
The system supports multiple custom bots by:
- Storing bot-specific information in app configuration
- Dynamic bot name resolution in channel operations
- Preserving custom bot names across re-authentications

### 5. Usage
## Migration from Bot Token

If you're migrating from the previous bot token approach:

1. The app maintains backward compatibility with `botToken` prop
2. OAuth tokens take precedence over bot tokens when both are present
3. Update your app configuration to use OAuth instead of direct bot tokens
4. The `teamId` is now automatically obtained during OAuth flow
5. Custom bot information is preserved across OAuth flows

## Security

- πŸ”’ Tokens are stored securely in the app configuration
- πŸ”„ Automatic token refresh prevents expired token issues
- πŸ›‘οΈ OAuth scopes limit app permissions to only what's needed
- 🌐 HTTPS is required for redirect URLs in production
- πŸ” Client secrets are handled securely and never exposed in frontend

## Troubleshooting

### Selection Interface Issues

1. **Selection page not showing**: Ensure OAuth start URL doesn't include bot type parameters
2. **Custom credentials not working**: Verify Client ID and Secret are correct
3. **Theme not persisting**: Check browser localStorage support

### Common OAuth Issues

1. **"Team ID is required" error**: Ensure OAuth flow completed successfully and `teamId` is set
2. **"Invalid redirect URI" error**: Check that redirect URL matches exactly in Slack app settings
3. **"Invalid scope" error**: Verify all required scopes are added to your Slack app
4. **Token refresh failures**: Check that `client_secret` is correctly configured

After OAuth setup, the app will automatically:
- Exchange authorization codes for access tokens
- Store tokens securely in the app configuration
- Refresh tokens automatically when they expire
- Provide a `SlackClient` instance for API operations
### Custom Bot Issues

1. **Invalid Client Credentials**: Ensure your Client ID and Client Secret are correct
2. **Insufficient Permissions**: Make sure your Slack app has all required OAuth scopes
3. **Redirect URI Mismatch**: Verify the redirect URI in your Slack app settings matches

### Debug Mode

Enable debug logging by checking the browser developer tools or server logs for OAuth-related errors.

## Development

The app uses the MCP (Multi-Channel Platform) OAuth utilities for token management and HTTP client creation. The main components are:

- `mod.ts` - Main app configuration with OAuth setup
- `client.ts` - Slack API client with OAuth support
- `utils/constants.ts` - OAuth URLs and scopes
- `utils/client.ts` - TypeScript interfaces for API endpoints
- `utils/ui-templates/page-generator.ts` - Bot selection interface HTML generation
- `loaders/oauth/start.ts` - OAuth initiation with selection interface
- `actions/oauth/callback.ts` - OAuth completion with custom bot support

## Contributing

When contributing to this app:

1. Test both deco.chat bot and custom bot flows
2. Ensure the selection interface works on both light and dark themes
3. Verify mobile responsiveness of the selection page
4. Test credential validation and error handling
5. Maintain backward compatibility with existing bot token approach

## API Methods

Expand Down Expand Up @@ -105,6 +290,39 @@ const response = await slack.uploadFileV2({
});
```

## Custom Bot Configuration

### Setting Up a Custom Bot

1. **Create Your Custom Slack App** following steps 1-3 above
2. **Use Custom Scopes** - Choose appropriate scopes for your bot's functionality
3. **Configure Bot Name** - Set a unique identifier for your bot

### Bot Name Usage

The bot name is used in:
- Channel welcome messages: `"To interact with me, just mention @your-bot-name in your messages!"`
- Channel listings: Shows `@your-bot-name` instead of `@deco.chat`
- App configuration: Stored as `customBotName` for future reference

**Bot Name Preservation**: During re-authentication or token refresh, the system preserves the previously configured custom bot name. A new `botName` parameter will override the existing configuration, while omitting it maintains the current setting.

### Multiple Bot Support

The system now supports multiple custom bots by:
- Storing bot-specific information in app configuration
- Dynamic bot name resolution in channel operations
- Preserving custom bot names across re-authentications

### Re-authentication Behavior

When OAuth runs again (token refresh, re-install):
- **With botName parameter**: Updates to the new custom name
- **Without botName parameter**: Preserves the existing custom bot name
- **First install**: Uses "deco.chat" as default if no botName provided

This prevents accidental loss of custom bot branding during routine re-authorizations.

## Migration from Bot Token

If you're migrating from the previous bot token approach:
Expand All @@ -113,6 +331,7 @@ If you're migrating from the previous bot token approach:
2. OAuth tokens take precedence over bot tokens when both are present
3. Update your app configuration to use OAuth instead of direct bot tokens
4. The `teamId` is now automatically obtained during OAuth flow
5. **New**: Custom bot information is preserved across OAuth flows

## Security

Expand Down
7 changes: 6 additions & 1 deletion slack/actions/deco-chat/channels/invoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ export default async function invoke(
if (challenge) {
return { challenge };
}

const botIdentifier = ctx.customBotName
? `@${ctx.customBotName}`
: DECO_CHAT_CHANNEL_ID;

const [joinChannel, channel, thread] = props.event.channel_type === "im"
? [DECO_CHAT_CHANNEL_ID, props.event.channel, props.event.user]
? [botIdentifier, props.event.channel, props.event.user]
: [props.event.channel, props.event.channel, props.event.channel];
const linkProps =
await ctx.appStorage.getItem<JoinChannelProps & { installId: string }>(
Expand Down
6 changes: 5 additions & 1 deletion slack/actions/deco-chat/channels/join.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { JoinChannelProps } from "../../../../mcp/bindings.ts";
import { DECO_CHAT_CHANNEL_ID } from "../../../loaders/deco-chat/channels/list.ts";
import type { AppContext } from "../../../mod.ts";

/**
Expand All @@ -25,9 +26,12 @@ export default async function join(
console.error("error joining channel", error);
});
if (props.agentName && props.agentLink) {
const botIdentifier = config.customBotName
? `@${config.customBotName}`
: DECO_CHAT_CHANNEL_ID;
await ctx.slack.postMessage(
props.discriminator,
`<${props.agentLink}|${props.agentName}> has joined the channel! To interact with me, just mention @deco.chat in your messages!`,
`<${props.agentLink}|${props.agentName}> has joined the channel! To interact with me, just mention ${botIdentifier} in your messages!`,
).catch((err) => {
console.error("error posting welcome", err);
});
Expand Down
Loading
Loading