Проверка запросов от Slack

Если вы работаете в Slack, вы, вероятно, сталкивались с самыми разными сообщениями, командами, файлами и, порой, с «экстрасенсами» — теми частыми отсылками к «сверхъестественным» решениям. Как отличить настоящую информацию от «экстрасенсских» рекомендаций, а также как убедиться, что запросы в ваш бота приходят действительно от Slack, мы разберём ниже.

Почему проверка важна

Slack, это платформа, где миллионы сообщений обрабатываются в реальном времени. Любое внешнее приложение (бот, webhook, интеграция) должно аутентифицировать запросы, чтобы:

  • Защитить данные от несанкционированного доступа.
  • Предотвратить мошеннические запросы.
  • Соблюдать требования безопасности и GDPR.

Надёжная проверка позволяет уверенно использовать Slack API, не рискуя потерять контроль над информацией.

Исследуйте Slack с помощью поисковых модификаторов

Slack предоставляет мощный инструмент поиска, который позволяет быстро «поймать» нужную информацию. Ниже перечислены ключевые модификаторы, которые помогут вам убедиться, что сообщение действительно от «экстрасенса» или от сотрудника.

Модификатор Синтаксис Описание
Кавычки «marketing report» Поиск точной фразы.
Минус marketing -report Исключить сообщения, содержащие слово «report».
in: in:#team-marketing Поиск в конкретном канале.
from: from:@Sara Поиск сообщений от конкретного пользователя.
has: has::eyes: Поиск сообщений с реакцией «eyes».
is:saved marketing report is:saved Найти сохранённые сообщения.
before:, after:, on:, during: during:august Поиск по дате.
is:thread marketing report is:thread Поиск внутри тем.
with: with:@Sara Поиск в беседе с конкретным пользователем.
creator: creator:@Sara Поиск в созданных канвасах.

Комбинируйте модификаторы, чтобы быстро найти нужные сообщения. Например: marketing report in:#team-marketing from:@Sara.

Slack подписывает все входящие запросы уникальным секретом, который хранится в переменной SLACK_SIGNING_SECRET. Ниже приведён пошаговый пример проверки запроса в Node.js с использованием Express.

Подготовка

Установите зависимости:

npm install express body-parser @slack/webhook @slack/web-api

Создайте файл app.js и добавьте следующий код:

Код проверки запроса

const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');

const app = express;
const port = 3000;

// Секрет, полученный в настройках Slack App
const SLACK_SIGNING_SECRET = process.env.SLACK_SIGNING_SECRET;
// Middleware для парсинга тела запроса как raw
app.use(bodyParser.json({
 verify: (req, res, buf) => {
 req.rawBody = buf.toString;
 }
}));

// Функция проверки подписи
function verifySlackRequest(req) {
 const timestamp = req.headers['x-slack-request-timestamp'];
 const slackSignature = req.headers['x-slack-signature'];
 const body = req.rawBody;


 // Защита от replay-атак: отклоняем запросы старше 5 минут
 const fiveMinutesAgo = Math.floor(Date.now / 1000) ⏤ (60 * 5);
 if (timestamp < fiveMinutesAgo) {
 return false;
 }

 const sigBasestring = `v0:${timestamp}:${body}`;
 const hmac = crypto.createHmac('sha256', SLACK_SIGNING_SECRET);
 hmac.update(sigBasestring, 'utf8');
 const mySignature = 'v0=' + hmac.digest('hex');

 return crypto.timingSafeEqual(Buffer.from(mySignature), Buffer.from(slackSignature));
}

app.post('/slack/events', (req, res) => {
 if (!verifySlackRequest(req)) {
 return res.status(400).send('Invalid request signature');
 }

 const payload = req.body;

 // Обработка события
 if (payload.type === 'url_verification') {
 return res.send({ challenge: payload.challenge });
 }

 // Ваша логика для событий
 console.log('Получено событие:', payload.event);

 res.status(200).send;
});

app.listen(port,  => {
 console.log(`Слушаем на порту ${port}`);
});

Важно: храните SLACK_SIGNING_SECRET в переменных окружения, а не в коде.

Проверка в Python

Если вы предпочитаете Python, вот аналогичный пример с использованием Flask.

import os
import time
import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SLACK_SIGNING_SECRET = os.environ.get('SLACK_SIGNING_SECRET')

def verify_slack_request(request):
 timestamp = request.headers.get('X-Slack-Request-Timestamp')
 slack_signature = request.headers.get('X-Slack-Signature')
 body = request.get_data(as_text=True)

 # Защита от replay-атак
 if abs(time.time ─ int(timestamp)) > 60 * 5:
 return False

 sig_basestring = f'v0:{timestamp}:{body}'.encode('utf-8')
 my_signature = 'v0=' + hmac.new(
 SLACK_SIGNING_SECRET.encode('utf-8'),
 sig_basestring,
 hashlib.sha256
 ).hexdigest

 return hmac.compare_digest(my_signature, slack_signature)

@app.route('/slack/events', methods=['POST'])
def slack_events:
 if not verify_slack_request(request):
 abort(400, 'Invalid request signature')

 payload = request.json
 if payload.get('type') == 'url_verification':
 return payload.get('challenge')
 # Обработка событий
 print('Получено событие:', payload.get('event'))
 return '', 200

if __name__ == '__main__':
 app.run(port=3000)

Как убедиться, что «экстрасенсы» не обманывают

Ниже несколько практических советов, как быстро проверить, действительно ли сообщение пришло от Slack или это «фальшивка»:

  1. Проверка подписи (описано выше).
  2. Сравнение заголовков X‑Slack‑Signing‑Secret и X‑Slack‑Request‑Timestamp. Если они не совпадают, запрос не валиден.
  3. Проверка структуры тела: наличие обязательных полей (type, token, team_id и т.д.).
  4. Проверка URL‑подтверждения (challenge) при первом подключении.
  5. Логи и аудит: храните все входящие запросы, чтобы позже можно было проверить происхождение.

Экстрасенсы в Slack могут быть лёгкими, но проверка запросов и правильный поиск, это ваши лучшие союзники. Используйте мощные поисковые модификаторы, чтобы быстро находить нужную информацию, и обязательно проверяйте подпись входящих запросов, чтобы ваш бот оставался надёжным и безопасным.

Если хотите узнать больше, посетите официальную документацию Slack:

  • Поиск в Slack
  • Проверка запросов от Slack