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:
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
- 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.
Click Create App button.
Then at Basic Information, scroll down to find your App Credentials.
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.
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.
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:
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.
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.
Also, on the same page, you need to enable permission scopes. Scroll down on the page to Scopes, and make sure
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:
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:
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
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.
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
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.
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:
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!