Slack bot request validation not working for button actions.If we have bold formatting tag * in the block kit U

571 views Asked by At

I have created a bot response using block-kit UI. In the message included one text message and button elements.For the text I applied bold formatting using *. So the message shown in the slack channel with the bold character as of now it is fine . But when the user performed the button action,the request validation got failing.

Here is the code : This Method in controller to accept the messages from Slack and to send message back to slack

    @PostMapping(path = "/slack")
   @ResponseBody
   public void handleSlackRequest(
      @RequestBody String requestBody) throws URISyntaxException
   {
      RestTemplate restTemplate = new RestTemplate();
      HttpHeaders headers = new HttpHeaders();
      Map<Object, Object> mainMap = new HashMap<>();
      mainMap.put("channel", "DXXXXXXXXX");
      mainMap.put("blocks",
         "[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"*Text message with bold characters.*\"}},{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"This is a section block with a button.\"},\"accessory\":{\"type\":\"button\",\"text\":{\"type\":\"plain_text\",\"text\":\"Click Me\",\"emoji\":true},\"value\":\"click_me_123\"}}]");
      URI uri = new URI("https://slack.com/api/chat.postMessage");
      headers.add("Content-Type", "application/json");
      headers.set("Authorization", "Bearer xoxb-11XXXXXXXX-13XXXXXXXXXX-Q2XXXXXXXXXXXXXXXXX");
      HttpEntity<Object> restrequest = new HttpEntity<>(mainMap, headers);
      ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.POST, restrequest,
         String.class);
      return;
   }

If we see in the block added this text message Text message with bold characters.

Shows the response like in the image https://i.stack.imgur.com/m0PCc.png

When click on the button the below method get trigger

 @PostMapping(path = "/slackaction", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
   @ResponseBody
   public void handleSlackActionsConversationEvent(

      @RequestHeader HttpHeaders headers,
      @ModelAttribute("payload") String requestPayload, @RequestBody String slackRequestActionMessage)
   {
      String slackRequestTimeStamp = headers.getFirst(SlackRequestHeaders.X_SLACK_REQUEST_TIMESTAMP.getHeader());
      String slackSignature = headers.getFirst(SlackRequestHeaders.X_SLACK_SIGNATURE.getHeader());
      boolean isValid = verifyIncomingSlackRequest(slackRequestActionMessage, slackRequestTimeStamp, slackSignature);
      return;
   }

I am using the below code to validate the request followed this [link] : https://api.slack.com/authentication/verifying-requests-from-slack

     public boolean verifyIncomingSlackRequest(String requestBody, String slackRequestTimeStamp, String slackSignature)
       {
          try
          {
             String signing_secret = "dXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
             String[] split = slackSignature.split("=");
             String versionNumber = split[0];
             String requestKey = versionNumber + ":" + slackRequestTimeStamp + ":" + requestBody;
             String siginingKey = encode(signing_secret, requestKey, versionNumber);
    
             return siginingKey.equals(slackSignature);
          }
          catch (Exception e)
          {
          }
          return false;
       }

  public String encode(String key, String data, String versionNumber) throws Exception
   {
      SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
      Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
      sha256_HMAC.init(secret_key);
      byte[] macBytes = sha256_HMAC.doFinal(data.getBytes());
      StringBuilder hashValue = new StringBuilder(2 * macBytes.length);
      for (byte macByte : macBytes)
      {
         hashValue.append(String.format("%02x", macByte & 0xff));
      }
      return versionNumber + "=" + hashValue.toString();
   }

When do button action and message contains * in the Slack request, the Validation is failing without * validation working fine.Did I missed anything or the approach is different?Please may I know any thoughts on this.

1

There are 1 answers

2
Jonathan Tadeo Leiva On

I had this exact problem. Although I'm using php, this might be useful to you.

$headers = getallheaders();

$raw_body = file_get_contents('php://input');

$x_slack_signature = $headers["X-Slack-Signature"];

$x_slack_timestamp = $headers["X-Slack-Request-Timestamp"];

$slack_signing_secret = "...";

Note the normal hyphens, not the underscore as you have in your code.

    /*

For computing the signature, I need the following:

    1. $version
    2. $x_slack_timestamp
    3. $raw_body
    
All of them appended to each other with a colon (:)

*/

$signature_base_string = $version . ":" . $x_slack_timestamp . ":" . $raw_body;

$hash_signature = "v0=" . hash_hmac('sha256', $signature_base_string, $slack_signing_secret);

After this I compare them and if they do not match then the request is invalid.