Tutorial: Developing an Action-able app
By: Tomomi Imura
Tags: Bots, Slack, Nodejs, JavaScript, How To

Tutorial: Developing an Action-able app

Making your Slack app accessible directly from a message

Actions let Slack users interact directly with your app from a message, similar to built-in actions like adding reactions or message sharing. When your app registers an action, users can interact directly with it from a Slack conversation, making it easier to create a task in a project management app, report an issue into a bug tracker, make a request to your IT helpdesk, or anything else you can dream up, all from a message. As a developer, adding actions not only makes your app more interactive but also makes it more discoverable by users who may not know the app is installed.

This tutorial will walk you through how to use the API to make your app actionable.

Building “ClipIt! for Slack”

You are going to create “ClipIt! for Slack”, a Slack app for a fictional service called ClipIt!. Let’s pretend you run a web service which allows users to “clip” some content of a web page and save it to a database. Your users can access the saved content from web or mobile, as the data is synchronized across platforms. You are going to build the companion app that runs on the Slack client, where your users can clip text from Slack messages using Actions.

This GIF shows how the Slack app works:

Actions in action!

Here’s a walkthrough of how a user interacts with ClipIt from Slack:

A user hovers a message and chooses Clip the message from the … menu A dialog opens to let the user give your app more information The user submits the dialog form ClipIt! for Slack exports the message to the ClipIt database ClipIt! for Slack DMs the user with a confirmation message

This tutorial is meant to be helpful for everyone who wants to learn about Slack APIs. These instructions use Node.js, so if you’d like to follow the how-to, make sure Node.js is installed on your machine. If you wish to keep developing Slack apps with Node.js afterward, check out Slack’s official Node SDK!

🐙🐱 The original source is on GitHub but I have also created its simplified version, which is used in this tutorial on Glitch. If you would like to “remix” the code sample, use this link, https://glitch.com/edit/#!/remix/slack-clipit-simplified so you can tweak the code by yourself.

⚙️ Configuring Your App

Sign in to your Slack account and create an app from https://api.slack.com/apps. Enter an App Name and select your development workspace.

Create an app — enter an app name and select a workspace

Click Create App button.

Then at Basic Information, scroll down to find your App Credentials.

App Credentials — scroll down to get the Signing Secret

You need to reveal the hidden Signing Secret and copy the code to keep it as an environmental variable: SLACK_SIGNING_SECRET in your .env file in the root of your Node app. I will explain what it is and how to use it at Verifying the Requests section in this tutorial.

SLACK_SIGNING_SECRET=15770a…

Scroll a bit more down to fill out the Display Information with your app icon and description any time.

Now, go to Interactive Components, and turn on Interactivity. Once it is enabled, you will see more fields appear on the page.

Interactive Component — Turn it on, then enter a Request URL

Then enter your Request URL, which is the URL where Slack sends the data payload to when the action is invoked by a user.

Note: This should be your server URL, where your application code runs. For example, if you host on Glitch during development, your URL should look something like https://example.glitch.me/actions. If you tunnel your localhost with service like ngrok, use the URL (e.g. https://example.ngrok.io, then add /actions). If you would like to set up ngrok, you can follow the instructions for using ngrok to develop locally for Slack.

Once you enter the Request URL, scroll down to Actions, and click Create New Action button. Fill the form out:

Create Action — Define your action here

Click Create, followed by Save Changes.

Next, go to Bot Users. Click Add a Bot User. This should allow you to define a name of the app bot.

Bot User — Enable a bot user

Then click Add Bot User button at the bottom of the page, then Save.

Next, go to OAuth & Permissions and click Install App to Workspace. Once you’ve installed it to your development space, the installation page will take you back to the OAuth & Permission page with access tokens. Copy the Bot user token and keep it in your .env file.

SLACK_ACCESS_TOKEN=xoxb-214…

Also, on the same page, you need to enable permission scopes. Scroll down on the page to Scopes, and make sure bot and command scopes are pre-selected.

Whew! You’ve taken care of the configuration for your app and you are ready to build.

☕️ Building an App

As I mentioned in the intro, I am using Node.js and ExpressJS instead of our SDK in this tutorial to show in more depth how to use the Slack API.

First, install the dependencies. ExpressJS and a middlewear, bodyParser, are used to handle POST requests. Also, I am using the axios HTTP request client with qs , a querystring parser:

$ npm install express body-parser axios qs dotenv --save

Let’s start with the core parts. We will modify the code later as we add more functions. First, create an index.js file. In this file, instantiate an Express app and make the server listen to an appropriate port:

Code snippet 1

Before you proceed, let’s take a look at this diagram to see how the app works.

Each flow is initiated when a user uses the actions from a message menu. As soon as the message_action event is triggered, Slack sends your app an event payload to the endpoint you specified earlier as a Request URL.

The endpoint can be written like this:

Code snippet 2

If the event type is message_action (= when the event came as a result of executing an action), your app opens a dialog.

In code snippet 2, where it says “open a dialog”, include this code that defines the dialog content structure, then open it in Slack client using the dialog.open method:

Code snippet 2.1

Here, use the axios module to perform a POST request to Slack, and when the dialog.open method successfully opens a dialog, send a HTTP status 200.

A dialog pops up

This endpoint is also called when the dialog is submitted by a user. In code snippet 2, where it says “Dialog is submitted”, you need to respond with an empty HTTP 200 response to let Slack knows the submission is received.

Then, let’s assume you are storing the “clipped” message in your app database, and finally send the user a confirmation message using the chat.postMessage method:

Code snippet 2.2

Sending the confirmation is an important process for the user and a good practice for user-experiences. Always keep in mind to close a loop!

Okay, let’s run the code and try your app on the Slack client. You should be able to view your app action in the message menu, and the app should work as expected besides the database part (unless you actually set it up!).

There’s just one more thing you need to do to make your app secure .

🔐 Verifying the Requests

Now you need to make your app more secure: use signing secrets to verify if the requests received are authentically from Slack. Always verify any request from Slack (for example, the request notifying your app that a user has used an action) before acting on it.

Signing secrets replace the old verification tokens, which you were using before if you have previously worked with Slack APIs, or followed my old tutorial. To make the verification process more secure, Slack sends an additional X-Slack-Signature HTTP header on each HTTP request.

The X-Slack-Signature is just the hash of the raw request payload (HMAC SHA256, to be precise), keyed by your app’s Signing Secret.

When you are using ExpressJS with body-parser, use the body-parser verify function option to get the raw request payload.

Let’s go back to code snippet 1, the top of your code. Replace the body-parser middleware settings where it says //The next two lines will be modified later to these:

Code snippet 3

I already have provided the cryptographic functionality in verifySignature.js, so just include the function in the beginning of your index.js:

Then, verify the request by comparing your signing secret against the hash at the event endpoint (See code snippet 2):

In this example, you need to verify only at this event endpoint. However, when you write any Slack apps in future, you must verify each time you receive payloads from Slack. (To learn more about signing secret, read Verifying requests from Slack.)

Run your Node code again, and if everything works fine, you’re done with your Action-able app! Congrats!

📄 Related Slack API Documentation