#9166: Fix: Use userToken for Slack file downloads
channel: slack
stale
Cluster:
Slack Media Handling Fixes
## Summary
Fixes #9153 - Slack file downloads now correctly use `userToken` for authentication when configured, instead of always using `botToken`.
## Problem
When users configured both `botToken` and `userToken`, OpenClaw always used `botToken` for file downloads, which lacks the necessary permissions in many Slack workspaces. This resulted in:
- HTML login pages saved instead of actual files
- Downloaded files in `media/inbound/` were corrupted
- Users had to manually download files using the `userToken` as a workaround
## Root Cause
The `resolveSlackMedia()` function in `prepareSlackMessage()` always passed `ctx.botToken` for file downloads, even when `userToken` was configured. The `userToken` was defined in the config but never propagated to the message handler.
## Solution
This PR implements a 3-step fix:
### 1. Add `userToken` to SlackMonitorContext
**File:** `src/slack/monitor/context.ts`
- Added optional `userToken?: string` field to `SlackMonitorContext` type
- Added `userToken` parameter to `createSlackMonitorContext()` function
- Included `userToken` in the returned context object
### 2. Pass `userToken` from config
**File:** `src/slack/monitor/provider.ts`
- Pass `slackCfg.userToken?.trim()` when creating the monitor context
- This ensures the userToken from config reaches the context
### 3. Use `userToken` for file downloads
**File:** `src/slack/monitor/message-handler/prepare.ts`
- Changed `resolveSlackMedia()` call from `token: ctx.botToken` to `token: ctx.userToken || ctx.botToken`
- Uses `userToken` when available, falls back to `botToken` if not configured
## Why This Works
- **userToken**: Has broader file access permissions (user-level scope)
- **botToken**: Has limited file access (bot-level scope)
- **Fallback**: Maintains backward compatibility for configs without userToken
## Impact
✅ **Fixes authentication** for Slack file downloads when userToken is configured
✅ **Backward compatible** - falls back to botToken if userToken not set
✅ **Minimal changes** - surgical 3-file fix affecting only file download flow
✅ **No breaking changes** - existing configurations continue working
## Testing
- ✅ Code follows existing patterns (`resolveToken` logic already used elsewhere)
- ✅ Properly handles optional `userToken` field
- ✅ Maintains existing behavior when userToken is not configured
🤖 Implemented by agent-af5f50c9d7c7
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR threads an optional Slack `userToken` through the Slack monitor context (context.ts, provider.ts) and prefers it over `botToken` when downloading attachments for inbound messages (prepare.ts), fixing cases where bot tokens lack file access.
One attachment path is still using the bot token: when handling a thread reply where the current message has no files but the thread-starter message has files, the code hydrates the starter attachments using the bot token only. That scenario will continue to fail in the same workspaces this PR aims to fix, so it should be updated to use the same user-token-first fallback.
<h3>Confidence Score: 4/5</h3>
- Mostly safe to merge, but one remaining token path can still break Slack attachment downloads in a common thread scenario.
- Changes are small and localized, but the thread-starter attachment hydration path still uses botToken, which contradicts the PR’s stated fix and will cause real download failures for some configurations.
- src/slack/monitor/message-handler/prepare.ts
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#20479: fix(slack): keep replies flowing for oversized file uploads
by olyashok · 2026-02-19
81.4%
#18763: fix(slack): add auth header when downloading forwarded attachment i...
by amabito · 2026-02-17
80.0%
#5036: docs: improve Slack setup and troubleshooting guide
by DanBatten · 2026-01-31
79.6%
#14847: fix(slack): preserve auth across Slack-hosted file redirects
by natashache · 2026-02-12
78.9%
#13486: fix: allow Slack HTTP mode without app token
by SepehrShapouri · 2026-02-10
78.8%
#19083: Slack: preserve per-thread context and consistent thread replies
by jkimbo · 2026-02-17
77.9%
#2917: Slack: fix thread context + prevent reply spillover
by SocialNerd42069 · 2026-01-27
77.3%
#20480: feat(slack): extract and surface attachment notes in messages
by olyashok · 2026-02-19
77.0%
#11347: fix: scope Telegram update offset to bot token
by anooprdawar · 2026-02-07
76.8%
#15863: fix: route agent-to-agent Slack messages to bound sessions
by MisterGuy420 · 2026-02-14
76.6%