Notice: Parts of this article from 2019 mention using Bearer to connect to the Slack API. Instead, we now recommend checking out our open source project Pizzly. You can use it to handle the oAuth portions mentioned in this article.
Like everyone, we use Slack a lot at Bearer. We have tons of channels, some for the whole team, some only for the guilds. We even have some for #coffee that we take remotely.
Like any other team, information gets lost a lot on Slack. So one thing that we try to do well its to pin important messages in each channel.
It can be a command to get up and running quickly on a project or just a link to our favorite restaurant menu. Pinning a message turned to be a big part of our Slack routine now - and we even pin messages in DM.
On Slack, you can see pinned messages with the little 📌 on top of a channel. Clicking on it opens a sidebar with a truncated version of the messages. You then need to click on each message to see its context.
The thing is that the FREE version of Slack doesn't let you access old messages. Turns out that the API does! So, we built an app for that.
Let's see how we did?
Understanding the Slack API
Let's start by having a look on Slack's API documentation, which reference a pins.list
endpoint having the following abstract:
And that request takes the following arguments:
The token in Slack documentation is a user token, more commonly known as an access token. And the channel argument is a channel identifier, which means that we need to first query another endpoint, channels.list
.
From there we can deduct what our API call flow will be:
- First, we will query the list of channels;
- Then, we will use a channel identifier and list its pinned messages.
Now, time to play 🤓!
Configuring the Slack API and generating a token
To help us use the Slack API, we will use Bearer below. First, we add the Slack API to Bearer's dashboard and follow the instructions provided:
We have to create a new Slack App:
Then, we configure the OAuth callback URL:
Finally, we grab our Slack credentials and add them to Bearer:
Well, the Slack seems well configured! Let's start to make API requests. But first, we have to generate an access token, this is required for every OAuth APIs. This token represents a user identity.
Usually handling OAuth is tricky, but here we will generate this token with Bearer. Go back to your Slack API on the Bearer's dashboard and click on Bearer's Connect to Slack button:
Bearer retrieves and stores this token and in return provides an authentication identifier (authId
). When calling the API with Bearer, we will use this authId
instead of the token.
This way Bearer will always make sure to pass the token and manage the refresh token automatically when needed ✨!
Calling the Slack API
We are ready to call the API. Here's how a request to the channels.list
endpoint looks like:
$ curl "https://proxy.bearer.sh/slack/channels.list" \
-H "Authorization: _REPLACE-WITH-YOUR-BEARER-SECRET-KEY_" \
-H "Bearer-Auth-Id: _REPLACE-WITH-YOUR-AUTH-ID_"
If you replace the above params with yours, Slack will successfully respond to your API call 🎉!! It shall return a list of all your channels.
Now, we can send a request to the pins.list
endpoint, using one of the channel ID previously retrieved (e.g. C4FE4TW9K).
$ curl "https://proxy.bearer.sh/slack/pins.list?channel=C4FE4TW9K" \
-H "Authorization: _REPLACE-WITH-YOUR-BEARER-SECRET-KEY_" \
-H "Bearer-Auth-Id: _REPLACE-WITH-YOUR-AUTH-ID_"
I can hear some of you saying: don't we need to pass the token
as well? Well, as we said previously, using the connect button, Bearer handles the token arguments. It knows where to pass it and what value it is!
The whole logic and API flow is working. It's time to implement this Slack API integration into a proper-application.
An application to retrieve pinned messages
We are going to use Vue.js, which is an awesome framework to build a simple app like this one. No backend, only plain HTML, CSS and a bit of JS.
If you add the Bearer's Javascript API client on top to perform the API calls, it's starting to look magical.
For instance, here's how the app fetches Slack channels:
slack
.auth("AN-AUTH-ID-GENERATED")
.get('/channels.list')
.then(({ data }) => {
if (data.ok && data.channels) {
this.channels = channels
}
})
And the function fetching pinned messages from a previously selected channel:
slack
.auth("AN-AUTH-ID-GENERATED")
.get(`/pins.list?channel=${this.selectedChannelId}`)
.then(({ data }) => {
if (data.ok && data.items) {
this.messages = data.items
}
})
A note on front-side API call: When calling an API from a client-side context, you need to be extra careful about security. Bearer gives you an option to enable client-side calls, using a publishable key.
We are almost done, but something is still missing on our application. So far, we've been using our own Slack identity, but we want to let anyone connect using their Slack identity and retrieve their own pinned messages. So it can work for any Slack's workspaces.
Adding Slack authentication
To let the user retrieves its own Slack channels and pinned messages, we need to let him/her connect using its Slack identity.
Bearer provides a JavaScript client (and a React component) that deals with such logic.
Once this component is added, our users are able to login using their Slack account. By using their identity, our application will perform API calls to Slack on behalf of their identity. That's exactly what we wanted.
Let's sum up! We just built a static app using Slack API. The entire OAuth flow and API calls are handled by Bearer. And it's deployed in production using Netlify 🚀
Try it out right here and open the source code to have a full overview.