Provider Guide
Slack
Handle Slack URL verification challenges and receive event payloads locally during development.
URL Verification challenge
When you add a Request URL in Slack, it sends a url_verification challenge. Anonymily can auto-respond via the Slack handshake preset (Pro) or you can handle it manually:
app.post('/slack/events', express.json(), (req, res) => {
// Respond to Slack's URL verification challenge
if (req.body.type === 'url_verification') {
return res.json({ challenge: req.body.challenge });
}
// Handle other events...
res.status(200).send();
});
Verify signatures
const crypto = require('crypto');
function verifySlack(rawBody, timestamp, signature, signingSecret) {
// Reject stale requests (> 5 minutes)
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const base = `v0:${timestamp}:${rawBody.toString()}`;
const expected = 'v0=' + crypto
.createHmac('sha256', signingSecret)
.update(base)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/slack/events', express.raw({ type: '*/*' }), (req, res) => {
const timestamp = req.headers['x-slack-request-timestamp'];
const signature = req.headers['x-slack-signature'];
if (!verifySlack(req.body, timestamp, signature, process.env.SLACK_SIGNING_SECRET)) {
return res.status(401).send('Invalid signature');
}
const body = JSON.parse(req.body.toString());
if (body.type === 'url_verification') {
return res.json({ challenge: body.challenge });
}
res.status(200).send();
});