We know Slack is an essential tool for streamlining developer workflows and making communication across the team easy which is why we make it simple to integrate StackHawk with your Slack workspace.
We wanted to share how we built the integration so other teams looking to do the same can learn from our experience.
Here we will walk through how we structured our production Slack app, the development process of building out our integration, and the security concerns we identified as we developed our app integration.
Know Before You Go: Pick Your Slack App Type
The first step in building a Slack integration is to create a new Slack App for your workspace. A Slack app is just a container for operations your Slack integration will perform, with resources to make that integration come alive. A Slack app is defined to be in varying stages of distribution, which include:
Not Distributed: The app can only be installed in your Slack workspace. All new Slack apps start in this state.
Distribution Activated: The app can be installed in other workspaces. It must have a redirect URL assigned that starts with
https://
, alongside other configuration.Submitted to App Directory: The app is being reviewed by Slack for submission to the app directory. Making changes to your app’s configuration is discouraged at this point. You have to jump through a lot of hoops and fill out all required fields to get to this state.
Starting with a “Not Distributed” app will let you dip your toes into Slack’s application ecosystem without having to do all the legwork expected of a fully distributed “Submitted to App Directory” Slack app.
Simple Slack Apps with Incoming Webhooks
No matter which level of distribution you choose, the most intuitive way to get started is with Slack’s incoming webhooks support. A Slack webhook is just a unique URL that is designed to post messages to the specific Slack channel you designate.
Getting Going with Webhooks
Once you have created your new Slack app, you can assign permissions and functionality to the application, including webhooks. Go to the Incoming Webhooks
tab and enable this functionality. From there, you can choose a channel within your Slack workspace, and that will create the unique webhook URI that you can post to.
To send messages with the webhook, simply make POST
request to that URL, providing a JSON message body with the desired payload you want to send. We can demonstrate this with a cURL command:
curl -X POST -H 'Content-type: application/json' --data '{ "text": "Hello World!" }' https://hooks.slack.com/services/MY/WEBHOOK
Messages sent in the text payload can include markdown formatting and even emojis using Slack’s colon syntax. This is a simple approach to create rich-text messages that will stand out. More advanced message payloads can be prepared and employed using Slacks Block Kit builder, which we will get into shortly.
curl -X POST -H 'Content-type: application/json' --data '{ "text": ":wave: Welcome friends! Check out my _sweet webhook_, pretty rad isn’t it? " }' https://hooks.slack.com/services/MY/WEBHOOK
The webhook URI can be used in automation scripts for your build processes. As long as you have the capacity to run a shell script and make outbound web requests, you can send messages to your internal Slack channels with ease.
‼️ Security Concern
Webhooks are technically secrets, and they will need to be stored alongside other sensitive strings for your application. You do not want to hard-code this URL and you especially should not commit a live webhook URL to source control. We recommend using AWS Parameter Store or a similar tool of your choosing to store your internal webhook as a SecureString.
Advanced Messages with Block Kit
Webhooks are intentionally tied to the workspace and channel they post to, and they can’t leverage the full power of Slack’s API. At StackHawk, we used incoming webhooks to get going with internal build notifications. As we went on to build a more sophisticated Slack app to submit to the App Directory we had to pivot our strategy to something more sophisticated due to usability concerns and security challenges.
We knew we were ready to zhuzh up our notifications with the full power of Slack’s messaging API. This is where Slack’s Block Kit builder comes into play.
The Slack Block Kit is a framework to help structure and plan out complex messages sent by an application backend, and preview those messages in Desktop or Mobile viewports. The Slack Block Kit framework is just a fancy and consistent mechanism of building complex dialogs in nested JSON objects. These JSON objects define a consistent structure and pattern for inputs to enable rich formatting and user interactivity. Slack has strong reference documentation on these.
The Good: Block Kit Builder and Slack SDK
Example messages built in the Block Kit builder show the corresponding JSON in the right panel, and can be shared by their URL which contains the full JSON payload escaped as query parameters. This quality makes them conducive to sharing for feedback amongst a team.
Once a message is shared with the URL, tweaks can be made by either party, and the functional result is available and saved. Once fully constructed, The JSON payload can then be copied and sent to a webhook with a cURL command.
Beyond just their Block Kit builder, Slack also provides SDKs to interact with their API in code.
These are language specific libraries that are conducive to working with complex Slack messages. At Stackhawk, we utilized the Slack Java SDK to send our integration messages and retrieve workspace resources dynamically. Slack also maintains NodeJS and Python SDKs as well, alongside a long list of tools for working with their API. Depending on your backend technology stack, you should consider using these libraries for building out your Slack app’s messaging.
The Bad: Attachments and Emojis
As we developed our Slack app and prepared the messages we would send, we did discover some subtleties of the Slack API in development. While blocks are in, Slack attachments are out.
Slack attachments are identifiable by the colored vertical bar that wraps the attachment content. Slack is discouraging additional use of attachments because of uncertainty in message hierarchy. Attachments are meant to convey secondary, facultative content rather than primary information.
Example of Slack Attachment
As we were first developing our Slack messages, we strongly considered using attachments (and even found a bug related to attachments in the Java SDK!) to accommodate our original designs.
Initial Design of Slack Integration Using Attachments
The reason Slack is moving away from attachments is because attachment content can be hidden, truncated or wrapped behind a “show more detail” context entirely at the Slack viewport’s discretion. Block content is meant to be the primary focus, and won’t be treated this way.
We also want to mention some difficulty in displaying inline images with our Slack content. The Block Kit builder has an image block specific for displaying content focused around a given image image, and images as left or right aligned content. But inline images alongside text to convey information have little support at the moment. Hosted images can be added to inline text within a context block, but this is not standard text objects.
The Slack recommended approach for inline images is to use emojis, and leverage the Slack workspace “custom emojis” that can be sent with the :smiley:
syntax. This approach works great for internal workspaces, where members will have full control over their workspace custom emojis. This approach wont work for production apps, however. There are currently no app scopes that allow for a Slack app to add emojis to a workspace (hint: it’s not this one, or this one, or this one). This is a shame, as the inline custom emojis are an elegant solution that just almost works, but can’t go the distance for your production app.
Use of an Emoji using the :emoji:
Syntax
These subtle nuances around inline images, customized workspace emojis and the transition to blocks led to a few cycles spent on redesigning our messages to accommodate Slack’s new preferred message structure.
The Scopes: Picking your Privileges
In order to leverage the Slack API to its full potential, you will want to pick out the right scopes for your application. Slacks scopes table reference is comprehensive, and all over the place. It took a lot of studying and practice with scopes to find the right combination our app would need. In the end we picked these scopes for our desired functionality:
chat:write and chat:write.public to send messages to public channels
channels:read for listing public channels in the workspace
groups:read for private channel discovery and invitation
team:read for retrieve workspace information
Remember, scopes should only ever be additive. As you start to distribute your Slack app, don’t remove integrations from the app unless absolutely necessary.
Now Get Building!
Slack’s tools for advanced messages suited us nicely. This shared tooling helped StackHawk’s engineers prototype faster with our designer. While still a little rough around the edges, we look forward to any improvements Slack can make to their Block Kit framework, and we recommend using it as part of the message prototyping phase of your application development.