From slack-go-sdk
OAuth flows, token management, and security best practices for Slack apps. Use when implementing app distribution, multi-workspace installations, token storage and rotation, managing scopes and permissions, or securing production Slack applications.
How this skill is triggered — by the user, by Claude, or both
Slash command
/slack-go-sdk:slack-auth-securityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Bot Token** (`xoxb-`):
Bot Token (xoxb-):
User Token (xoxp-):
import "github.com/slack-go/slack"
// Step 1: Generate authorization URL
state := generateRandomState()
authURL := fmt.Sprintf(
"https://slack.com/oauth/v2/authorize?client_id=%s&scope=%s&state=%s",
clientID,
"chat:write,channels:read",
state,
)
See oauth-flow.md for complete OAuth implementation.
// NEVER hardcode tokens
// Use environment variables or secrets manager
token := os.Getenv("SLACK_BOT_TOKEN")
api := slack.New(token)
// Rotate tokens periodically
newToken, err := api.RotateTokens(refreshToken)
if err != nil {
return err
}
// Update stored token
storeToken(newToken)
See token-management.md for storage strategies and rotation patterns.
Messaging:
chat:write - Send messageschat:write.public - Post to channels bot isn't inChannels:
channels:read - View public channelschannels:manage - Create/manage channelsgroups:read - View private channelsUsers:
users:read - View usersusers:read.email - View user emailsSee scopes-permissions.md for comprehensive scope guide.
Always verify requests from Slack:
import "github.com/slack-go/slack"
func verifySlackRequest(r *http.Request, signingSecret string) bool {
verifier, err := slack.NewSecretsVerifier(r.Header, signingSecret)
if err != nil {
return false
}
body, _ := ioutil.ReadAll(r.Body)
verifier.Write(body)
return verifier.Ensure() == nil
}
Never use HTTP endpoints for webhooks:
https://your-app.com/slack/eventshttp://your-app.com/slack/eventsImplement rate limiting to avoid abuse:
type RateLimiter struct {
requests map[string][]time.Time
mu sync.Mutex
}
func (rl *RateLimiter) Allow(userID string, maxRequests int, window time.Duration) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
cutoff := now.Add(-window)
// Remove old requests
var validRequests []time.Time
for _, t := range rl.requests[userID] {
if t.After(cutoff) {
validRequests = append(validRequests, t)
}
}
if len(validRequests) >= maxRequests {
return false
}
rl.requests[userID] = append(validRequests, now)
return true
}
Store tokens separately for each workspace:
type WorkspaceToken struct {
TeamID string
BotToken string
BotUserID string
InstalledAt time.Time
}
func getAPIForTeam(teamID string) (*slack.Client, error) {
token, err := loadTokenForTeam(teamID)
if err != nil {
return nil, err
}
return slack.New(token.BotToken), nil
}
Programmatically configure apps:
manifest := &slack.Manifest{
DisplayInformation: slack.ManifestDisplayInformation{
Name: "My Bot",
Description: "Helpful bot",
},
Features: slack.ManifestFeatures{
BotUser: &slack.ManifestBotUser{
DisplayName: "mybot",
AlwaysOnline: true,
},
},
OAuthConfig: slack.ManifestOAuthConfig{
Scopes: slack.ManifestOAuthScopes{
Bot: []string{"chat:write", "channels:read"},
},
},
}
_, err := api.CreateManifest(manifest)
See manifest-api.md for manifest patterns.
See security-checklist.md for comprehensive security audit:
npx claudepluginhub linehaul-ai/linehaulai-claude-marketplace --plugin slack-go-sdkBuilds Slack apps with the Bolt framework in Python, JavaScript, or Java. Covers Block Kit UIs, slash commands, event handling, OAuth, and Workflow Builder integration.
Bootstraps an aweek-branded Slack app via API, provisions Socket-Mode and bot tokens, and persists credentials to enable Claude chats through `aweek serve` SlackAdapter.