Add a Slack Chatbox Directly into Your React App
Tags: javascript, react, slack, productivity
Published: 2023-07-11 11:37:06

---
title: Add a Slack Chatbox Directly into Your React App
published: true
date: 2023-07-05 00:00:00 UTC
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnqx2fbh3z7vu9ji8zu3.png
tags: javascript, react, slack, productivity

---

## Introduction

Like every company, we always try to be there for our users, answer questions, get feedback, and help them get the most out of our product. One of the ways we do that is by using  **Slack**. For every Pro/Enterprise account in our app, we create a dedicated Slack channel and invite the account users to that channel.

Of course, users can just use their Slack app to communicate with us, but we wanted to make it easier for them. For this reason, we created an embedded chat box directly in our app, through which they can communicate with their dedicated Slack channel, ask questions, get support, and give us feedback. Additionally, it allows all the users from one organization to see the messages sent to the channel and the answers you provide. This way, they can get immediate support for questions they may have during their usage of our app.

In this article, we will share a basic example of building a Slack-based chat box in your frontend app. We will show an innovative way to interact with Slack APIs from the frontend app, and how to use FoAz to secure access to the Slack APIs. At the end of the reading, you'll also have a working example of a Slack-based chat box that you can use in your app.

<video autoplay="autoplay" controls="" muted="">
          <source src="https://media.graphassets.com/x97qqexzTNebkjHoihDn" type="video/mp4" title="React Based"></source>
          Sorry, your browser doesn't support embedded videos.
        </video>
## Slack APIs

Slack is an API-first product, with a very rich set of APIs. This means everything that can be done through the UI, can be done using APIs as well. They also allow us to build an automated workflow that drives all the cool applications you see in Slack. 

We will use two APIs for our chat box: One is the [conversations.history](https://api.slack.com/methods/conversations.history "https://api.slack.com/methods/conversations.history") API, which allows us to read the messages from the channel, and the second is the [chat.postMessage](https://api.slack.com/methods/chat.postMessage "https://api.slack.com/methods/chat.postMessage") API, which allows us to  send messages. Both of these APIs are HTTP-based endpoints that allow us to create a chat box in our frontend app.

Looking at the documentation of the chat.postMessage endpoints, we can see that it requires a token to be sent as part of the request. We don't want to use the user's token, as not all of the app users will have access to the channel or Slack account, so we want to use a bot token. This token will belong to a bot that will send and retrieve messages from the channel.

Using such a token has two challenges we need to deal with:

1. We cannot expose the token in the frontend app, as it will allow anyone to find it and send messages to the channel.

2. We want only admin users of our app will be able to send messages to the channel. Regular users have no SLA to send support messages to the channel.

To deal with those challenges, we will use [<u>FoAz</u>](https://www.permit.io/foaz "https://www.permit.io/foaz"), a feature in Permit.io that allows us to call backend APIs from the frontend app and define better permissions for "root" level tokens and secrets.

## FoAz

**F**rontend  **O**nly  **A**uthori**z**ation (Or, FoAz) solves two major problems for us:

1. It allows frontend apps to call backend APIs without exposing the backend API keys in the frontend app by using the user's frontend (temporary) JWT.

2. It allows us to define better permissions for "root" level tokens and secrets.

While you can implement FoAz yourself by following the open standard at [foaz.io](https://foaz.io/ "https://foaz.io/"), we will use Permit.io to implement FoAz in our app. For the purpose of this demo, let's start by configuring our FoAz to secure the calls to the Slack APIs in Permit.io. If you haven't signup to Permit.io yet, you can do it [here](https://app.permit.io/ "https://app.permit.io/").

**Note: In order to follow the technical demo in this article, you must have installed Node.js/npm on your computer.**

## Create Slack App

To call Slack APIs, we need to create a Slack app that will allow you to call their APIs and use a bot to send messages.

To create Slack app, you can follow these steps:

1. In [<u>https://api.slack.com</u>](https://api.slack.com "https://api.slack.com") - login with your Slack credentials and click Your Apps in the top right corner

2. Click on Create New App in the top right corner of your applications list

3. Your app should have the following permissions and a bot, you can configure it manually or just paste the following app manifest (change it per your needs)

    ```json
    {
        "display_information": {
            "name": "Permit.io (bot)",
            "description": "Permit.io Announcement Bot",
            "background_color": "#3a2f26"
        },
        "features": {
            "bot_user": {
                "display_name": "GreetBot",
                "always_online": false
            }
        },
        "oauth_config": {
            "scopes": {
                "bot": [
                    "channels:history",
                    "channels:read",
                    "chat:write",
                    "users:read"
                ]
            }
        },
        "settings": {
            "org_deploy_enabled": false,
            "socket_mode_enabled": false,
            "token_rotation_enabled": false
        }
    }
    ```

## Configure Chat Permissions

Let's start our tutorial by setting up the necessary configuration required to create the chat box.

### Users and Roles

To create secure access, we will first need to define users and roles. In your app, you'll probably already have a way to authenticate your users, but to save time in this example, we will use Permit.io to create mock users and roles. For a full guide on setting up roles and permissions in Permit.io, [<u>check out this tutorial</u>](https://www.permit.io/blog/rbac-with-permit "https://www.permit.io/blog/rbac-with-permit"). 

1. Create the following roles in Permit.io:
    - admin - This role will be used to allow users to send messages to the Slack channel.
    - user - This role will be used to allow users to read messages from the Slack channel.
2. Create the following users in Permit.io:
    - `thor@foaz-chatbox.app` - This user will be assigned to the admin role.
    - `someone@foaz-chatbox.app` - This user will be assigned to the user role.
 ![Add users.png](https://media.graphassets.com/GprSwoK0QNufOkFYN1kG "Add users.png")

### Slack API Access

Now that we have the users and roles, we can configure access to the Slack APIs. In the Permit.io app sidebar menu, you'll find a page called FoAz Proxy. This page allows you to configure the access to the Slack APIs, and to define the permissions for the users and roles we created in the previous step.

1. Create a new FoAz Proxy by clicking the Add Configuration button.

2. Assign it a name, for example, Slack Chat

3. In the URL field, assign the following URL to read Slack messages `slack.com/api/conversations.history`

4. In the method, choose the `POST` method

5. In the `Resource` dropdown, choose to Create New and create a new resource named `Chat` with the actions of `read` and `send`
    ![Add Resource.png](https://media.graphassets.com/lbNunpD2S2mXiMyhI69a "Add Resource.png")
6. Choose the action `Read` for the mapping rule we just created
7. Click on + Mapping Rule and paste the following URL `slack.com/api/chat.postMessage` in it, choose the method post, and assign `Chat` and `send` as action and resource
8. Repeat the previous step and paste the following URL `slack.com/api/users.list` in it, choose the method `GET`, and assign `Chat` and `read` as action and resource
    ![FoAz Config.png](https://media.graphassets.com/QuIpBw4SF6w8BS9VF0Wk "FoAz Config.png")

### Chat Permissions

Now that we have configured the building blocks of our permission model (Roles, Actions [HTTP Methods], and Resources [URLs]), we can now create the permissions for the users and roles we created in the previous step. In the Policy Editor tab, let's mark the following permissions for our two roles:

 ![Proxy Config.png](https://media.graphassets.com/bbIHptbQmyo9lPDFqmwZ "Proxy Config.png")

At this point, we have all our permissions configured, and we can start using the FoAz proxy to call the Slack APIs from our frontend app. Let's clone a sample widget and try to use our new chat box.

## Clone the Sample Widget

To save time, we created a sample widget that you can use to build your own Slack-based chat box. Although this widget is written in React, you can use the same approach in any frontend framework you use.

1. Clone the [<u>following repository</u>](https://github.com/permitio/foaz-slack-example "https://github.com/permitio/foaz-slack-example")
    ```bash
    git clone git@github.com:permitio/foaz-slack-example.git
    ```
    
2. In the terminal, from the same directory you just cloned the project, Install the dependencies for our demo
    ```bash
    npm install
    ```
    
3. Configure the right Slack channel where you want to send the messages in the .env file (to get the channel ID, right-click on the channel name, choose Copy Link, and grab the ID from the link you copied)
    ```bash
    VITE_REACT_APP_Slack_CHANNEL_ID=<YOUR_Slack_CHANNEL_ID>
    ```
    
4. Configure the Proxy ID by copying the configuration ID from Permit’s app to the relevant environment variable in the .env file.
    ![FoAz ID.png](https://media.graphassets.com/YZKf28fTZKe4nOMEfLCJ "FoAz ID.png")
    
5. Start the development server
    ```bash
    npm run dev
    ```
    
6. Open the browser at [http://localhost:](http://localhost:5173/ "http://localhost:5173/")5173, and login with the `thor@foaz-chatbox.app` user we created in the previous step.

At this point, you should see a chat box in the bottom right corner of the screen. If you try to send a message, you'll see that FoAz cannot authorize you to send the message, as we didn't connect our login method to the FoAz proxy yet.

## Configure the Proper JWKs

FoAz uses the user's JWT token to call the backend APIs. The way that FoAz verifies the user's identity is by validating the [<u>JWT token against the public JWKs supplied by the authentication authority</u>](https://docs.permit.io/foaz/fetching-jwks/?_gl=1*101hr7q*_ga*MTY3MDU2NTUyNy4xNjc4ODY2NzEw*_ga_SPFKH5NXDE*MTY4Nzg2MTQ3MC4xMTAuMC4xNjg3ODYxNDcwLjAuMC4w#what-are-jwks "https://docs.permit.io/foaz/fetching-jwks/?\_gl=1\*101hr7q\*\_ga\*MTY3MDU2NTUyNy4xNjc4ODY2NzEw\*\_ga\_SPFKH5NXDE\*MTY4Nzg2MTQ3MC4xMTAuMC4xNjg3ODYxNDcwLjAuMC4w#what-are-jwks"). This method is supported by all the major authentication providers, and you can find the JWKs URL in the authentication provider's documentation.

In our case, tho, to avoid the mess of configuring the authentication provider, we will use mock JWKs that we will configure in Permit.io. To find your JWKs configuration, in the terminal window where you started the sample widget, you should see the following message:

```bash
 --- Public JWKS --- 
{"keys":[{"kty":"RSA","kid":"tvPApr70xhk-RJrKgXuTeIz9KyNjrf_6NABfvh61rCA","use":"sig","alg":"RS256","e":"AQAB","n":"qgSzmsz-Astj1FjJdqqnkaW-696aQTxrjPB7U-_uk0pto4cbTrnWihNBs791Itr0MX0XX_7BO3z-SILEcyP75vDapcn0vleJ_t-Kd1uQPiNKaUClqFqN8QmoyIE7CBCp196QfgAVVBTMgGsKXwNpGFKQg35QmKhbKlA92Ahj14S3C7B0L7OhrEUk3T9tM4QIhgbnyG_xUXT7StNE3lw-3SwS1qIU1-pQXE7OPWkcv5GEnlIxXaoxqhQZrQE77YIxgrRVrA6fbQdTLhNELO_1ZWOyFIkcRr9AJX1-Ar-92n5StHIZfIwl5-sKC931k1JgkCfuxklrbrbcgmwKR_3BlQ"}]}
```

As this is the public key Permit.io will use to validate the JWT token, we need to configure it in Permit.io.

In Permit.io UI, go to Settings -> JWKs and add the JWKs from the logs in your relevant environment.

 ![Config JWKs.png](https://media.graphassets.com/UoNEb1pSwQlSzV9iZ1FA "Config JWKs.png")

Let's now go back again to the sample widget, and try to send a message again. This time, you should see that the message was sent successfully.

## Verify the Proper Permissions

As we mentioned before, we want to allow only admin users to send messages to the Slack channel. To verify that, let's try to login with the `someone@foaz-chatbox.app` user we created in the previous step, and try to send a message.

 ![Chat Example.png](https://media.graphassets.com/gpyWzgyvRm60qo7smJMM "Chat Example.png")

As you can see, this time the message was not sent, as the user doesn't have the proper permissions to send messages to the Slack channel. Yet, we still can read the messages from the channel, as we configured the proper permissions for the user role.

One of the coolest things you can achieve by using FoAz is permissions that do not depend on the code of your application. In this example, we can now change the checkbox in the Policy Editor tab, and allow the user role to send messages to the Slack channel. If you try to send a message again, you'll see that this time the message was sent successfully.

## Use the Chat Box in Your App

Although the code we used to demonstrate the chat box is not production ready (as it lacks error handling, edge cases, etc.) you can get a good idea of how to create one yourself in your app.

In the app.tsx file, you’ll find the required elements for the interactive chat box. We base our app on material-UI which means you can customize it according to your specific UI needs. In the same file, you’ll also find the way we utilize a useSlack hook that helps us with all the data we need to get and send to the Slack APIs. Use it as-is or create your needed hook yourself.

```tsx
const { slackUser, setSlackUser, messages, send, loading, sending } = useSlack();
```

In the useSlack file, you’ll find first the functions we used to generate mocks of the JWT and a wrapper to the fetch function that call the Slack APIs via FoAz proxy. You’ll also find the hook itself that contains the relevant function to manage all the chat flow we manage with Slack.

```ts
const proxyFetch = async (url: string, user: string, method: string, body: any) => {
    const token = await generateJWT(user);
    const res = await fetch(`https://proxy.api.permit.io/proxy/${PROXY_ID}?url=${url}`, {
        method,
        body: body ? JSON.stringify(body) : undefined,
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        }
    });
    const json = await res.json();
    const status = res.status;
    return { status, json };
}
```

## Conclusion

At this point, you should have enough knowledge to create your own chat box and use FoAz to secure access to the Slack APIs. As the next step, we invite you to think of more creative FoAz ways to create cool new worlds in your frontend apps.

You can read more on FoAz as a standard in [foaz.io](https://foaz.io/ "https://foaz.io/"), and join our community [<u>working group in Slack</u>](https://io.permit.io/FoAz-community "https://io.permit.io/FoAz-community") to contribute to the standard and the open-source project.

Happy FoAzing!