bolt-python icon indicating copy to clipboard operation
bolt-python copied to clipboard

message event in one app being sent to Request URL in another app

Open christopherhan opened this issue 6 months ago • 12 comments

I have two Slack apps under the same team / workspace:

  • App 1. Production app that is set to POST events to a Request URL / HTTPS endpoint
  • App 2. Development app that is set to use WebSockets

My goal is to develop under App 2 before deploying to production under App 1. I have App 1 deployed on a k8s cluster in AWS that receives message events with Bolt just fine, and events are POSTed to my request URL.

If I do a simple request with App 2's tokens and channel IDs with chat.postMessage/test endpoint here, it successfully delivers the message to App 2's channel, but I see from App 1's production logs that it also attempts to send a POST request to App 1's Request URL configured. I ensured that App 1 and App 2 tokens are not being mixed up. My assumption was that if I configured my Bolt app with App 2's tokens, then the apps would be isolated (i.e. a message sent to App 2 is not sent to App 1)

Reproducible in:

The slack_bolt version

# pip freeze | grep slack
slack-bolt==1.18.0
slack-sdk==3.26.1

Python runtime version

# python --version
Python 3.11.7

OS info

# uname -v
#1 SMP PREEMPT Mon Nov 8 11:22:26 UTC 202

I'm running Slack bolt app inside a docker container. The above is running the command inside a running container.

Steps to reproduce:

Configure two apps in the same workspace team

  1. One with Socket Mode off and POSTs requests to the Request URL
  2. One with Socket Mode on
  3. Install both apps in the same workspace (the two apps are listed under the Apps section of the sidebar in the Slack desktop app
  4. Visit chat.postMessage/test
  5. Post a message using App 2's Bot token and channel ID obtained from App 2 in the Apps section of the sidebar
  6. Observe that the message was sent to App 2's channel, but it also sent a payload to App 1's endpoint

Expected result:

Message from chat.postMessage/test is sent only to App 2's channel and payload is NOT sent to App1's Request URL

Actual result:

The chat.postMessage/test message was sent to App 2's channel successfully, but it also sent a payload to App 1's Request URL.

Here's a snippet of App 1's logs

[2023-12-27 11:58:39] {__init__.py:202} DEBUG - Installation data missing for enterprise: none, team: <redacted>: [Errno 2] No such file or directory: '/mnt/efs/slack/installations/none-<redacted>/installer-<redacted>-latest'
[2023-12-27 11:58:39] {base_client.py:251} DEBUG - Sending a request - url: https://www.slack.com/api/auth.test, query_params: {}, body_params: {'team_id': '<redacted>'}, files: {}, json_body: None, headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': '(redacted)', 'User-Agent': 'Python/3.11.7 slackclient/3.26.1 Linux/5.10.201-191.748.amzn2.x86_64'}
[2023-12-27 11:58:39] {base_client.py:542} DEBUG - Received the following response - status: 200, headers: {'date': 'Wed, 27 Dec 2023 11:58:39 GMT', 'server': 'Apache', 'vary': 'Accept-Encoding', 'x-slack-req-id': 'a714a5f3b034471fea55b601b501685a', 'x-content-type-options': 'nosniff', 'x-xss-protection': '0', 'pragma': 'no-cache', 'cache-control': 'private, no-cache, no-store, must-revalidate', 'expires': 'Sat, 26 Jul 1997 05:00:00 GMT', 'content-type': 'application/json; charset=utf-8', 'x-oauth-scopes': 'channels:read,groups:read,chat:write,app_mentions:read,channels:history,commands,groups:history,im:history,incoming-webhook,mpim:history,users.profile:read,reactions:read', 'access-control-expose-headers': 'x-slack-req-id, retry-after', 'access-control-allow-headers': 'slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, x-b3-flags', 'strict-transport-security': 'max-age=31536000; includeSubDomains; preload', 'referrer-policy': 'no-referrer', 'x-slack-unique-id': 'ZYwRbyiCpuimxPjc3FTrSQAAECE', 'x-slack-backend': 'r', 'access-control-allow-origin': '*', 'content-length': '196', 'via': '1.1 slack-prod.tinyspeck.com, envoy-www-iad-movnsdlb, envoy-edge-pdx-bivryhjg', 'x-envoy-attempt-count': '1', 'x-envoy-upstream-service-time': '153', 'x-backend': 'main_normal main_canary_with_overflow main_control_with_overflow', 'x-server': 'slack-www-hhvm-main-iad-pxeh', 'x-slack-shared-secret-outcome': 'no-match', 'x-edge-backend': 'envoy-www', 'x-slack-edge-shared-secret-outcome': 'no-match', 'connection': 'close'}, body: {"ok":true,"url":"https:\/\/<redacted>.slack.com\/","team":"<redacted>","user":"<redacted>","team_id":"<redacted>","user_id":"<redacted>","bot_id":"<redacted>","is_enterprise_install":false}
[2023-12-27 11:58:39] {listener_error_handler.py:67} ERROR - Failed to run listener function (error: 1 validation error for SlackMessagePayload
event -> client_msg_id
  field required (type=value_error.missing))
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/slack_bolt/listener/thread_runner.py", line 120, in run_ack_function_asynchronously
    listener.run_ack_function(request=request, response=response)
  File "/usr/local/lib/python3.11/site-packages/slack_bolt/listener/custom_listener.py", line 50, in run_ack_function
    return self.ack_function(
           ^^^^^^^^^^^^^^^^^^
  File "/var/www/app/routers/router.py", line 80, in handle_message
    message = SlackMessagePayload(**body)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for SlackMessagePayload
event -> client_msg_id
  field required (type=value_error.missing)
INFO:     172.16.1.83:29506 - "POST /app1/endpoint HTTP/1.1" 200 OK # the endpoint configured in App 1

The Exception above is expected, because my production app is receiving a payload that it's not expecting. This is how the Bolt app is configured in production

oauth_settings = OAuthSettings(
    client_id=SLACK_CLIENT_ID,
    client_secret=SLACK_CLIENT_SECRET,
    scopes=oauth_required_scopes,
    installation_store=FileInstallationStore(base_dir="/mnt/efs/slack/installations"),
    state_store=FileOAuthStateStore(expiration_seconds=600, base_dir="/mnt/efs/slack/states")
)

bolt_app = App(
    signing_secret=SLACK_SIGNING_SECRET,
    oauth_settings=oauth_settings
)
bolt_app_handler = SlackRequestHandler(bolt_app)

@bolt_app.event("message")
def handle_message(body, say, logger):
    ...
## Requirements

Please read the [Contributing guidelines](https://github.com/slackapi/bolt-python/blob/main/.github/contributing.md) and [Code of Conduct](https://slackhq.github.io/code-of-conduct) before creating this issue or pull request. By submitting, you are agreeing to those rules.

christopherhan avatar Dec 27 '23 12:12 christopherhan