DEV Community

Vincent Voyer
Vincent Voyer

Posted on

5 3

How to verify signatures from Slack incoming requests with Next.js

Hi there, this is a short blog post for anyone looking to handle Slack incoming requests with Next.js.

When creating a Slack application that will interact with your web application, Slack will call you back on some actions like:

Here's an example Slack postMessage call:

import { WebClient } from "@slack/web-api";
const web = new WebClient(token);
web.postMessage({
  channel: "#general",
  // fallback for mobile and email notifications:
  text: "Please visit <https://google.com>",
  blocks: [{
    type: "section",
    text: {
      type: "mrkdwn",
      text: "Please visit https://google.com"
    }
  }, {
    type: "actions",
    elements: [{
      type: "button",
      text: {
        type: "plain_text",
        text: "google",
      },
      url: `https://google.com`,
      action_id: "go_to_google_button",
    }],
  }]
});
Enter fullscreen mode Exit fullscreen mode

If you do this, you'll get this result:

Screenshot of a Slack message with a button.

And if you click on the "google" button, it will open Google in your browser. Pretty cool way to link from Slack to your web app for example.

But, that's not the end of the story. If you only do this then Slack will complain because a button, even if it only open a new url, is still an interactive element from Slack point of view.

So Slack will try to call the URL defined in your application "Interactivity & Shortcuts" Slack settings.

And it will fail because you've not defined a route for that.

Now to solve that, if you're using Next.js, you have to define a route as follow:

// pages/api/slackInteractiveEndpoint.js

import { createMessageAdapter } from "@slack/interactive-messages";

// you can find this secret in your app "Basic information" tab
const slackInteractions = createMessageAdapter(slackSigningSecret); 

slackInteractions.action(
  { type: "button", actionId: "go_to_google_button" },
  // no need to reply, it's just a button to a url
  () => {},
);

export default slackInteractions.requestListener();

export const config = {
  api: {
    bodyParser: false,
    externalResolver: true,
  },
};
Enter fullscreen mode Exit fullscreen mode

Then add this route in your Slack application "Interactivity & Shortcuts" tab. Test one message, click on the button and .. voilà!

Because the Slack SDK is responsible for parsing the body and replying to the request, we tell Next.js to let it go via:

  • bodyParser: false
  • externalResolver: true

Hope this helped you! Post a comment otherwise :)

Image of Datadog

Master Mobile Monitoring for iOS Apps

Monitor your app’s health with real-time insights into crash-free rates, start times, and more. Optimize performance and prevent user churn by addressing critical issues like app hangs, and ANRs. Learn how to keep your iOS app running smoothly across all devices by downloading this eBook.

Get The eBook

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay