Slack and Salesforce Integration: Authentication

This is another installment in my ongoing Slack and Salesforce integration series.

In part 2 (Slash Commands) and part 3 (Bots), I used an “integration user” to access Salesforce on behalf of Slack users. In other words, all Slack users connected to Salesforce using the same Salesforce user. This may be fine in some cases where everybody shares a common data set, but in most cases, you want Slack users to authenticate with Salesforce individually so that Slack requests execute in the specific context of the user, with the right set of permissions.

Slack doesn’t have built-in authentication for Salesforce, but it’s easy to implement a custom authentication process which I’ll demonstrate in this article.

Watch the video to see the custom authentication process in action:


In part 2, I described how to create a lightweight Node.js app that acts as a message broker between Slack and Salesforce. To implement our custom authentication process, we will add some code to the Node.js app to maintain a mapping between Slack user ids and Salesforce access tokens.

Here is the high level flow:

  1. Slack passes the Slack user id with each request to the service that implements a Slash Command, and with each message to Bots.
  2. When a request comes in, we check if we already have a Salesforce access token for the provided Slack user id.
  3. If we do, we call the Salesforce REST API using that token.
  4. If we don’t, we return a link that the user can click to authenticate with Salesforce using OAuth.

    Notice that the link includes the Slack User Id that is passed along throughout the OAuth process. You could encrypt that user id for additional security.
  5. At the end of the OAuth process, we will have both the Slack user id and a Salesforce access token. We store that mapping at the server-side so that the next time the user makes a request, we can retrieve the access token and use it to make the REST call to Salesforce.
  6. If the token becomes invalid, the REST call returns a 401 (not authorized) error, and we again present the login link to the user.

Source Code

The source code is available in this GitHub repository.

Code Highlights:

  • In this example, I keep track of the Slack User Id / Salesforce access token mappings in memory (see slack-salesforce-auth.js for details). In other words, Slack users will have to re-login to Salesforce if the Node.js app is restarted. You could also persist the tokens in a database. In that case you should encrypt the tokens before storing them.
  • The current version of the application doesn’t implement a refresh token workflow. When the token expires, the user will be presented with the login link again.
  • Slack also passes the integration token with each request. You should always verify that token before you handle the request to make sure an unauthorized user that gained access to a Slack user id can’t access Salesforce information by accessing the Node.js endpoint directly. For example, here is how I check the token for the /contact Slash command:
    if (req.body.token != CONTACT_TOKEN) {
        return res.send("Invalid token");

Additional Resources

Also check out the Slack/Salesforce integration in the DreamHouse sample app.