Securing your Slack apps

Jim Ray
Slack Platform Blog
4 min readNov 20, 2018

Security is at the forefront of our work at Slack — it’s vital that your team’s data remain safe and secure. This includes access via our APIs and the apps you are building for your team.

We’re continuing to improve our security features for apps; here are some you may want to investigate to make sure your app is buttoned up.

Restrict tokens to specific IP ranges

One of the most straightforward ways to help secure your app, with no changes to your existing code, is to enable IP address restrictions for your app’s tokens. Enabling this feature will mean Slack only accepts requests to the Web API from a pre-set list of IP addresses you configure in your app’s settings.

If the request matches the IP ranges you specify, Slack will process it just as we otherwise would. However, if Slack receives a request using your token from an IP outside of this range, we respond with an invalid_auth error.

You can enable IP by managing your app from api.slack.com/apps then clicking on the OAuth & Permissions feature, where there will be a section called “Restrict API Token Usage”. You can enter up to ten IP ranges using CIDR notation to specify either a range or single address. Saving the IP ranges will take effect immediately and won’t require you to reinstall your app.

This feature is available to internal apps only, meaning those not listed for public distribution, and for calls from your app to Slack’s Web API methods.

Request signing

The Slack API also includes a way for your app to verify that requests are actually coming from Slack using request signing. This involves using a shared secret that’s unique to your app to verify every request Slack sends. Request signing is supported by API methods where Slack is sending data to your app, including slash commands, Events API requests, interactive messages, actions, message buttons, message menus, and legacy outgoing webhooks.

With every request Slack sends your app, we include an HTTP header called X-Slack-Signature that includes an HMAC-SHA256 keyed hash. This hash is computed using a secret unique to your app as the key. This shared secret is found on your app’s management page on the “Basic Information” section under the heading Signing Secret.

To verify the signature, first create a basestring by concatenating the version number (currently always v0), the value of the X-Slack-Request-Timestamp HTTP header, and the message body of the request itself, using a colon (:) as a delimiter. An example basestring might look something like this: v0:1538352000:token=abc123def456xyz....

Compute a SHA256 hash using this basestring and your app’s shared signing secret as the key. The resulting hash should match the value of the X-Slack-Signature header; if it doesn’t, your app should throw away the request.

Because the hash is computed using both the timestamp and the body of the request, you can be confident the request itself wasn’t altered in transit between Slack and your app. If necessary, the shared secret can be regenerated directly from your app’s admin page.

If you’ve previously used static verification tokens to validate requests, that method is now considered deprecated and we will be dropping support at some point in the future. Request signing is more secure, doesn’t send your shared secret along with each request, and allows you to verify the contents of the request remain unchanged in transit, protecting you from man-in-the-middle attacks. Request signing is also supported in our official SDKs for Node.js and Python, so support is baked right in.

We’ve written a full, step-by-step walkthrough for validating requests with request signing.

Two-way authentication with mutual TLS

Request signing is a straightforward way to secure your app with a minimal amount of change to your application code. However, you may wish to handle authentication using cryptographically signed certificates via a TLS server. Both TLS and request signing allow you to verify the requests are coming from Slack and the content of the message hasn’t changed; however, mutual TLS relies on certificate verification rather than computing a hash of the request itself. It’s up to you to decide where you prefer to perform the verification.

Using mutual TLS requires you to be able to configure a TLS-terminating server and inject a custom header into the request before forwarding it to your application. Your application will then check the value of this header to ensure the request actually came from Slack. We’ve written a recommended process for using mutual TLS with your app.

Questions or feedback? Send us a note at devsupport@slack.com or tweet @SlackAPI. We’re excited to see what you build!

--

--