/salesforce-slack-starter-kit

Salesforce Slack Starter Kit - a minimal opinionated scaffold for building Slack Apps Integrated to Salesforce

Primary LanguageJavaScriptCreative Commons Zero v1.0 UniversalCC0-1.0

Salesforce Slack Starter Kit

Before looking into this project, we recommend you look into Apex SDK for Slack (currently in pilot for ISVs). Be sure to check back Salesforce developer blog regularly for announcements on future milestones of Salesforce Slack SDK. If you want to become part of the pilot, contact your technical account manager.

If you decide to build a custom Slack App integrated with Salesforce from scratch, this project can help you get started.

Current Limitation

  1. Do not use this if you are building the Slack app for AppExchange/Slack App Directory

  2. Multiple salesforce org connections to a single Slack workspace are not supported.

Note that Apex SDK for Slack plans to support above features.

About the Project

This project helps you to create an opinionated minimum scaffold for building a Slack Apps that integrates Salesforce data using Bolt SDK (Node.js version) and jsforce.

The scaffolded app follows the monorepo approach. It contains a Slack App implemented using Bolt SDK (Node.js) and it also setups the needed Salesforce data and metadata for managing users and authentication. The scaffold provides configuration files to host and run the app on Heroku.

Most of Salesforce and Heroku setup tasks are automated to cut down a number of manual configurations required to set up development environments.

We also configure environment variables required for local development, debugging, and testing.

The project assumes you want to run the Slack App in the Salesforce user context.

If you want to use a single Salesforce user (Integration user) for performing all data operations in Salesforce from Slack, check out Salesforce Slack Starter Kit (Server to Server Integration).

App Architecture

System Architecture

The image below shows the systems involved in the application.

App Architecture

Heroku acts as middleware and hosts the Node.js app that connects to Slack APIs (through Slack Bolt) and Salesforce APIs (through jsforce). To get familiar with the app's system architecture, you can watch this short video and familiarize yourself with the app's system architecture.

We use Heroku environment variables to securely manage necessary configuration variables related (such as clientId, consumer key and signing secret) to Slack and Salesforce connection.

Heroku App <-> Salesforce

The app uses jsforce and the OAuth 2.0 Web Server Flow for Web App Integration flow to connect to Salesforce.

Once the user successfully authorizes Slack workspace to Salesforce, we persist the access and refresh tokens. This allows the app to perform subsequent requests to Salesforce as an authorized user.

We store the tokens securely in a Salesforce custom object called Slack_Authentication__c:

Slack_Authentication__c
├── Access_Token\_\_c
├── Refresh_Token\_\_c
├── Slack_User_ID\_\_c
├── User\_\_c

On each request, the app needs to query this object to find if the user has already authorized. Although in reality, it first tries to retrieve this info from a cache that we've implemented to improve performance. As at this stage we don't know if the user is authorized yet, we need to use the OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration flow to perform this first step.

Once authorized, the app uses the stored access and refresh tokens to perform requests to Salesforce in the context of the authorized user.

These are the three possible scenarios for the authorization process:

Tokens cached

Tokens not cached

User not authorized

Heroku App <-> Slack

The Heroku App connects to Slack using Bolt.js.

Prerequisites

To be able to run this project you will need:

  • git (download here)
  • node >= 14 (download here)
  • Salesforce Org
    • If you don't have one, sign up for a free Developer Edition org.
    • If you want to use scratch orgs follow the instructions to enable Dev Hub in your Salesforce Developer Org.
  • sfdx CLI >= sfdx-cli/7.129.0 (download here)
  • Heroku account (signup)
  • heroku CLI (download here)

Setup Steps

Configuring Slack app at api.slack.com

  1. Open https://api.slack.com/apps/new and choose From an app manifest
  2. Choose the workspace you want to install the application to
  3. Copy the contents of manifest.yml into the text box that says Paste your manifest code here and click Next
  4. Review the configuration and click Create
  5. Now click Install App on the left menu. Then click the Install to Workspace button and then click on Allow

Deploying the app using a Salesforce Non-scratch org and Heroku

  1. Clone the salesforce-slack-starter-kit repository
git clone https://github.com/developerforce/salesforce-slack-starter-kit
  1. Authenticate to your Salesforce org and set as default:
sfdx auth:web:login --setdefaultusername -a mydevorg
  1. Login to your Heroku Account
heroku login
  1. Run Deployment Script
cd salesforce-slack-starter-kit/scripts
npm install
cd ..
node scripts/deploy.js
  1. Choose Non-Scratch Org when the script prompts you to select Salesforce environment

  2. The script prompts you to enter value for SLACK_BOT_TOKEN. To enter this value open your apps configuration page from this list, click OAuth & Permissions in the left hand menu, then copy the value in Bot User OAuth Token and paste into terminal.

  3. The script prompts you for slack signing secret SLACK_SIGNING_SECRET. To enter this value open your apps configuration page from this list, click Basic Information and scroll to the section App Credentials and click show button and copy the Signing Secret and paste into terminal.

Deploying the app using a Salesforce scratch org and Heroku

  1. Clone the salesforce-slack-starter-kit repository
git clone https://github.com/developerforce/salesforce-slack-starter-kit
  1. Authenticate to your Salesforce org that has DevHub enabled
sfdx auth:web:login --setdefaultdevhubusername -a DevHub
  1. Login to your Heroku Account
heroku login
  1. Run Deployment Script
cd salesforce-slack-starter-kit/scripts
npm install
cd ..
node scripts/deploy.js
  1. Choose Scratch Org when the script prompts you to select Salesforce environment

  2. The script prompts you to enter value for SLACK_BOT_TOKEN. To enter this value open your apps configuration page from this list, click OAuth & Permissions in the left hand menu, then copy the value in Bot User OAuth Token and paste into terminal.

  3. The script prompts you for slack signing secret SLACK_SIGNING_SECRET. To enter this value open your apps configuration page from this list, click Basic Information and scroll to the section App Credentials and click show button and copy the Signing Secret and paste into terminal.

Configuring Heroku Domain URL in Slack app Manifest

  1. To configure Heroku domain open your apps configuration page from this list, click App Manifest.

  2. Find the request_url fields in the manifest and modify it to replace heroku-app with your actual heroku domain name.

    At the end of this step your request_url should look like https://<heroku-domain>.herokuapp.com/slack/events

Deployment Script Actions

The scripts/deploy.js automates deployment of Slack app built using Bolt SDK (Node.js version) and Salesforce App.

The high-level overview of actions performed by the deployment script is listed below.

  1. Salesforce Org Setup

The script prompts you to Select the Salesforce Development Environment type. The script creates a scratch org using the provided dev hub if you choose a scratch org-based development. The script then deploys the source code and the associated metadata and assigns the necessary permission set to the user.

  1. Generation of certificate needed for JWT Bearer flow OAuth flow

We generate a private key and digital certificate to set up the JWT Bearer flow for authentication.

  1. Salesforce ConnectedApp deployment

Both the JWT Bearer and the Web Server flows need a connected app to be deployed to Salesforce. We use the same connected app for both flows. In the case of JWT bearer flow, a consumer key and a digital certificate is needed. In the case of Web Server flow, a consumer key, consumer secret and a callback URL are needed. All these configuration values are autogenerated and setup in the connected app, that we deploy to Salesforce.

  1. Heroku Bolt Node.js app creation and deployment

Finally, we create a Heroku app, setup all the needed configuration variables and deploy the Bolt Node.js app.

We also write the configuration variables to a .env file for local development

Directory Structure

├── force-app             # Folder that holds Salesforce metadata types
├── scripts
|   ├── deploy            # Scripts to automate scratch org creation, heroku
|   |                     #environment
│   ├── deploy.js         # Automated Deploy script launch file
│   └── templates         # Template for Connected apps setup
├── apps
     ├── salesforce-slack-app # Node.js Slack app
        ├── config              # Configs for Slack app
        |── listeners           # Modules to listen event for actions,
        |                       # shotcuts and view events in Slack
        |── middleware          # Middleware for Salesforce
        |                       # Authentication using OAuth 2.0 Web based flow
        |── routes              # Route for OAuth callback
        |
        ├── app.js              # Main file for Slack app launch
        ├── user-interface      # User Interface folder for Home page
        |                       # Modals and Messages in Block Kit format
        |
        ├── salesforce          # Folder for Salesforce integration related code
              ├── server-server-auth.js # Module to establish Salesforce connection using JWT
              ├── user-user-auth.js # Module to establish Salesforce connection using Web based OAuth 2.0
        ├── manifest.YAML       # Slack app manifest file
        ├── Procfile            # Heroku Procfile for deployment

How to Build and Deploy Code

Building Salesforce app using a Scratch Org

  • For Salesforce metadata synchronization in scratch orgs use sfdx force:source:pull to retrieve and sfdx force:source:push to deploy metadata from orgs to local project folder force-app

Building Salesforce App Using Non-Scratch Org

  • For Salesforce metadata synchronization in developer orgs use sfdx force:source:retrieve -p force-app/main/default to retrieve and sfdx force:source:deploy -p force-app/main/default to deploy metadata from orgs to local project folder force-app

Building and deploying Bolt Node.js app

  • For the Bolt Node.js app use the steps below:
    • cd into apps/slack-salesforce-starter-ap folder cd apps/salesforce-slack-app
    • add git remote to app repo using heroku git:remote -a <heroku app name>
    • run git push heroku main to push code to Heroku

Local Development

  1. To use ngrok, first install it downloading the executable or with npm:
$ npm install ngrok -g
  1. Next you’ll have to sign up for a free ngrok account.
  2. Once logged in, navigate to “Setup & Installation“ and copy your auth token.
  3. Then set your auth token in your local machine:
$ ngrok authtoken my_auth_token
  1. Run the ngrok tunnel as follows:
$ ngrok http 3000
  1. Copy the ngrok tunnel URL to the following places:
  • Your manifest file request URLs
  • The HEROKU_URL environment variable in your .env file
  • The Callback URL for the connected app that’s used for authorization in Salesforce - simply add the ngrok URL in a new line
  1. Now you are prepared to run the app locally! In another terminal different from the one in which you’re running ngrok, execute node app.js from the project folder. You can then make changes to the code and restart the app as many times as you want.

How to Test the Salesforce Connection

  1. Authenticate to Salesforce by navigating to app home and clicking on Authorize with Salesforce button.

You will need the password of your scratch org. You can generate one using sfdx force:user:password:generate --targetusername scratchorg

Authorize with Salesforce

  1. Once successfully authorized, run the Global Shortcut command Whoami that ships with the app as shown in the below screenshot

Global shortcut

  1. Successful connection output is similar to screenshot below

Successful Output

Note: the command can fail the first time you execute it if you are using Free Tier of heroku app as dynos sleep if left ideal. Restart the app to resume.

Considerations for Production app

Troubleshooting

  • Connected apps activation takes couple minutes. In case the app fails with a 400 error for JWT auth, wait for 2 minutes and give a retry.
  • If the app is failing, tail Heroku logs to see any errors

Further Reference