Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@slack/socket-mode
Advanced tools
Official library for using the Slack Platform's Socket Mode API
@slack/socket-mode is an npm package that allows developers to interact with Slack's Socket Mode API. This package enables real-time communication with Slack by establishing a WebSocket connection, which can be used to receive events and send messages without the need for a public HTTP endpoint.
Establishing a WebSocket connection
This code sample demonstrates how to establish a WebSocket connection using the @slack/socket-mode package. The `App` class is instantiated with the necessary tokens, and the `start` method is called to initiate the connection.
const { App } = require('@slack/socket-mode');
const app = new App({
appToken: 'xapp-1-A1234567890-123456789012-abcdef1234567890abcdef1234567890abcdef',
token: 'xoxb-123456789012-1234567890123-abcdef1234567890abcdef1234567890'
});
(async () => {
await app.start();
console.log('⚡️ Bolt app is running!');
})();
Listening for events
This code sample shows how to listen for 'message' events using the @slack/socket-mode package. When a message event is received, the event details are logged, and a response is sent back to the user who sent the message.
app.event('message', async ({ event, say }) => {
console.log(event);
await say(`Hello, <@${event.user}>!`);
});
Sending messages
This code sample demonstrates how to send messages using the @slack/web-api package in conjunction with @slack/socket-mode. The `WebClient` class is used to send a message to a specific channel.
const { WebClient } = require('@slack/web-api');
const web = new WebClient('xoxb-123456789012-1234567890123-abcdef1234567890abcdef1234567890');
(async () => {
await web.chat.postMessage({
channel: '#general',
text: 'Hello, world!'
});
})();
@slack/bolt is a framework for building Slack apps using JavaScript. It provides a higher-level abstraction compared to @slack/socket-mode, making it easier to build and manage Slack apps. While @slack/socket-mode focuses on WebSocket connections, @slack/bolt offers a more comprehensive set of tools for handling events, commands, and interactions.
slack-client is a package that provides a client for interacting with Slack's Real Time Messaging (RTM) API. It allows for real-time communication with Slack, similar to @slack/socket-mode, but it is more focused on the RTM API rather than the newer Socket Mode API.
$ npm install @slack/socket-mode
These examples show the most common features of Socket Mode
. You'll find even more extensive documentation on the
package's website and our api site.
This package is designed to support Socket Mode, which allows your app to receive events from Slack over a WebSocket connection.
The package exports a SocketModeClient
class. Your app will create an instance of the class for each workspace it communicates with. Creating an instance requires an app-level token from Slack. Apps connect to the Socket Mode API using an app-level token, which starts with xapp
.
Note: Socket Mode requires the connections:write
scope. Navigate to your app configuration and go to the OAuth and Permissions section to add the scope.
const { SocketModeClient } = require('@slack/socket-mode');
// Read a token from the environment variables
const appToken = process.env.SLACK_APP_TOKEN;
// Initialize
const client = new SocketModeClient({appToken});
After your client establishes a connection, your app can send data to and receive data from Slack. Connecting is as easy as calling the .start()
method.
const { SocketModeClient } = require('@slack/socket-mode');
const appToken = process.env.SLACK_APP_TOKEN;
const socketModeClient = new SocketModeClient({appToken});
(async () => {
// Connect to Slack
await socketModeClient.start();
})();
Bolt apps register listener functions, which are triggered when a specific event type is received by the client.
If you've used Node's EventEmitter
pattern
before, then you're already familiar with how this works, since the client is an EventEmitter
.
The event
argument passed to the listener is an object. Its content corresponds to the type of
event it's registered for.
const { SocketModeClient } = require('@slack/socket-mode');
const appToken = process.env.SLACK_APP_TOKEN;
const socketModeClient = new SocketModeClient({appToken});
// Attach listeners to events by type. See: https://api.slack.com/events/message
socketModeClient.on('message', (event) => {
console.log(event);
});
(async () => {
await socketModeClient.start();
})();
To respond to events and send messages back into Slack, we recommend using the @slack/web-api
package with a bot token
.
const { SocketModeClient } = require('@slack/socket-mode');
const { WebClient } = require('@slack/web-api');
const socketModeClient = new SocketModeClient(process.env.SLACK_APP_TOKEN);
const webClient = new WebClient(process.env.BOT_TOKEN);
// Attach listeners to events by type. See: https://api.slack.com/events/message
socketModeClient.on('member_joined_channel', async ({event, body, ack}) => {
try {
// send acknowledgement back to slack over the socketMode websocket connection
// this is so slack knows you have received the event and are processing it
await ack();
await webClient.chat.postMessage({
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `Welcome to the channel, <@${event.user}>. We're here to help. Let us know if you have an issue.`,
},
accessory: {
type: 'button',
text: {
type: 'plain_text',
text: 'Get Help',
},
value: 'get_help',
},
},
],
channel: event.channel,
});
} catch (error) {
console.log('An error occurred', error);
}
});
(async () => {
await socketModeClient.start();
})();
The client's connection to Slack has a lifecycle. This means the client can be seen as a state machine which transitions through a few states as it connects, disconnects, reconnects, and synchronizes with Slack. The client emits an event for each state it transitions to throughout its lifecycle. If your app simply needs to know whether the client is connected or not, the .connected
boolean property can be checked.
In the table below, the client's states are listed, which are also the names of the events you can use to observe the transition to that state. The table also includes descriptions for the states and arguments that a listener would receive.
Event Name | Arguments | Description |
---|---|---|
connecting | The client is in the process of connecting to the platform. | |
authenticated | (connectData) - the response from apps.connections.open | The client has authenticated with the platform. This is a sub-state of connecting . |
connected | The client is connected to the platform and incoming events will start being emitted. | |
ready | The client is ready to send outgoing messages. This is a sub-state of connected | |
disconnecting | The client is no longer connected to the platform and cleaning up its resources. It will soon transition to disconnected . | |
reconnecting | The client is no longer connected to the platform and cleaning up its resources. It will soon transition to connecting . | |
disconnected | (error) | The client is not connected to the platform. This is a steady state - no attempt to connect is occurring. The error argument will be undefined when the client initiated the disconnect (normal). |
The client also emits events that are part of its lifecycle, but aren't states. Instead, they represent specific moments that might be helpful to your app. The following table lists these events, their description, and includes the arguments that a listener would receive.
Event Name | Arguments | Description |
---|---|---|
error | (error) | An error has occurred. See error handling for details. |
slack_event | (eventType, event) | An incoming Slack event has been received. |
unable_to_socket_mode_start | (error) | A problem occurred while connecting, a reconnect may or may not occur. |
The SocketModeClient
will log interesting information to the console by default. You can use the logLevel
to decide how much or what kind of information should be output. There are a few possible log levels, which you can find in the LogLevel
export. By default, the value is set to LogLevel.INFO
. While you're in development, it's sometimes helpful to set this to the most verbose: LogLevel.DEBUG
.
// Import LogLevel from the package
const { SocketModeClient, LogLevel } = require('@slack/socket-mode');
const appToken = process.env.SLACK_APP_TOKEN;
// Log level is one of the options you can set in the constructor
const socketModeClient = new SocketModeClient({
appToken,
logLevel: LogLevel.DEBUG,
});
(async () => {
await socketModeClient.start();
})();
All the log levels, in order of most to least information are: DEBUG
, INFO
, WARN
, and ERROR
.
You can also choose to have logs sent to a custom logger using the logger
option. A custom logger needs to implement specific methods (known as the Logger
interface):
Method | Parameters | Return type |
---|---|---|
setLevel() | level: LogLevel | void |
setName() | name: string | void |
debug() | ...msgs: any[] | void |
info() | ...msgs: any[] | void |
warn() | ...msgs: any[] | void |
error() | ...msgs: any[] | void |
A very simple custom logger might ignore the name and level, and write all messages to a file.
const { createWriteStream } = require('fs');
const logWritable = createWriteStream('/var/my_log_file'); // Not shown: close this stream
const socketModeClient = new SocketModeClient({
appToken,
// Creating a logger as a literal object. It's more likely that you'd create a class.
logger: {
debug(...msgs): { logWritable.write('debug: ' + JSON.stringify(msgs)); },
info(...msgs): { logWritable.write('info: ' + JSON.stringify(msgs)); },
warn(...msgs): { logWritable.write('warn: ' + JSON.stringify(msgs)); },
error(...msgs): { logWritable.write('error: ' + JSON.stringify(msgs)); },
setLevel(): { },
setName(): { },
},
});
(async () => {
await socketModeClient.start();
})();
This package supports Node v14 and higher. It's highly recommended to use the latest LTS version of node, and the documentation is written using syntax and features from that version.
If you get stuck, we're here to help. The following are the best ways to get assistance working through your issue:
FAQs
Official library for using the Slack Platform's Socket Mode API
The npm package @slack/socket-mode receives a total of 317,877 weekly downloads. As such, @slack/socket-mode popularity was classified as popular.
We found that @slack/socket-mode demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 13 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.