Введение

Это вторая часть этой серии статей о создании Slack Command API с помощью Ruby. В первом посте мы настроили новое приложение, которое возвращает OK вызывающей стороне.



В этом посте мы поговорим о том, как авторизовать запросы Slack Commands, чтобы избежать недействительных запросов в нашем API.

Проверка запроса через токен

Согласно документации Slack Commands API:

Когда кто-то вводит косую черту, сообщение (и его данные) будут отправлены на настроенный внешний URL-адрес через HTTP POST. Вы, разработчик, должны что-то сделать с данными сообщения и ответить, если хотите.

Тело сообщения POST имеет следующую структуру параметров:

{
  "token"=>"XXXXX",
  "team_id"=>"YYYY",
  "team_domain"=>"ZZZZ",
  "channel_id"=>"UUUU",
  "channel_name"=>"directmessage",
  "user_id"=>"U1234567",
  "user_name"=>"anderson",
  "command"=>"/congratulate",
  "text"=>"@john for his new product release! It's brilliant!",
  "response_url"=>"https://hooks.slack.com/commands/YYYY/DDDDD/HASH"
}

И мы обязаны проверить, является ли сообщение действительным или нет, «подтвердив, что значение token соответствует токену проверки, который вы получили от Slack при создании команды».

Проверка на стороне сервера

Мы собираемся создать Rack Middleware, который перехватывает наш запрос и проверяет параметр token.

Если токен совпадает, мы должны продолжать возвращать пользователю «ОК». Если токен недействителен, мы должны вернуть конкретное сообщение, сообщающее пользователю Slack о необходимости установить правильный токен в приложении.

ПО промежуточного слоя для установки в стойку

Стойки Middleware полезны для перехвата запросов без изменения фактического метода обработчика. В этом случае мы собираемся создать промежуточное ПО под названием SlackAuthorizer.

Необходимо реализовать два метода:

  • initialize(app): отвечает за получение контекста приложения
  • call(env): отвечает за обработку фактического запроса, он должен возвращать действительное сообщение стойки, состоящее из массива с кодом состояния, хэшем заголовка и массивом с телом сообщения.

Вот реальная реализация класса SlackAuthorizer:

# app/slack_authorizer.rb
class SlackAuthorizer
  UNAUTHORIZED_MESSAGE = 'Ops! Looks like the application is not authorized! Please review the token configuration.'.freeze
  UNAUTHORIZED_RESPONSE = ['200', {'Content-Type' => 'text'}, [UNAUTHORIZED_MESSAGE]]
  def initialize(app)
    @app = app
  end
  def call(env)
    req = Rack::Request.new(env)
    if req.params['token'] == ENV['SLACK_TOKEN']
      @app.call(env)
    else
      UNAUTHORIZED_RESPONSE
    end
  end
end

Как вы можете видеть, если параметр token соответствует переменной env SLACK_TOKEN, мы отправляем запрос обратно в приложение, иначе мы должны ответить неавторизованным ответом стойки.

Обратите внимание, что мы отвечаем статусом 200. Это потому, что Slack ожидает 200 ответов, даже если у него какое-то неожиданное поведение, мы должны ответить статусом 200 для согласованности.

Подключите ПО промежуточного слоя

Следующим шагом является использование промежуточного программного обеспечения в приложении. Синатра делает это легко. Нам нужно буквально use вставить его в тело нашего приложения Sinatra:

require 'sinatra'
require_relative 'app/slack_authorizer'
use SlackAuthorizer
post '/slack/command' do
  'OK'
end

Настройте токен в производстве

Последний шаг — развернуть приложение, настроить переменную окружения токена и протестировать его.

Чтобы развернуть новую версию приложения, мы должны отправить ее в Heroku через git:

$ git add .
$ git commit -m 'Adding token authentication'
$ git push heroku master

В ПОРЯДКЕ. Новая версия приложения уже развернута, но мы еще не настроили токен. Давайте проверим, работает ли промежуточное ПО.

Запустите следующую команду в Slack:

/congratulate @john for doing a great job!

Вы должны увидеть что-то вроде этого:

Здорово! Давайте настроим переменную env токена в приложении Heroku:

Попробуй это

Теперь все настроено, давайте снова отправим команду /congratulate и посмотрим, что произойдет:

/congratulate @john for doing a great job!

Это означает, что мы настроили правильный токен подтверждения в Heroku.

Вывод

Оставлять API открытым для любого запроса небезопасно, и мы должны защитить приложение от этих недействительных сообщений POST.

В реальном приложении вы не будете использовать ПО промежуточного слоя так, как это сделали мы, потому что для любого вызова маршрута потребуется токен. Мы можем создать несколько приложений Sinatra::Base в одном и том же приложении Sinatra и использовать промежуточное программное обеспечение, например, в том, которое отвечает за slack-команды.

В следующем посте будет показано, как проверить параметры дохода и как вернуть правильную обратную связь пользователям.

Следуйте пошаговому кодированию по адресу: