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

No error triggering with ExpressReceiver and Lambda when missing OAuth Code

Open daga-segwise opened this issue 1 year ago • 5 comments

There is no error thrown when there is a missing OAuth code. We want to log all possible errors to Sentry and are unable to record this one through code. Only the error screen is thrown, but not able to find out the function where we would be able to catch this error.

image Have these three error handlers setup as well.

Reproducible in:

The Slack SDK version

"slack/bolt": "^3.14.0",

or refer to your package.json

Node.js runtime version

v18.18.0

OS info

ProductVersion: 14.1.1 BuildVersion: 23B81 Darwin Kernel Version 23.1.0: Mon Oct 9 21:28:45 PDT 2023; root:xnu-10002.41.9~6/RELEASE_ARM64_T6020

Steps to reproduce:

(Share the commands to run, source code, and project settings)

  1. Open the link - localhost:3001/slack/oauth_install - without the code parameters
  2. This should show an error screen
  3. This error is not thrown anywhere, not able to catch it by either using middleware or in processEventErrorHandler function

Expected result:

Error should be thrown in processEventErrorHandler

Actual result:

No error thrown anywhere

Requirements

For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. :bow:

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

daga-segwise avatar Jan 04 '24 10:01 daga-segwise

Can you share your code to reproduce this?

Note that depending on the app setup, the installation screen may not be managed by bolt (thus why I ask for code to reproduce the issue).

filmaj avatar Jan 04 '24 19:01 filmaj

The relevant code blocks are

Express Receiver

  const receiver = new ExpressReceiver({
    app: expressApp,
    signingSecret: config.SLACK_SIGNING_SECRET,
    clientId: config.SLACK_CLIENT_ID,
    clientSecret: config.SLACK_CLIENT_SECRET,
    stateSecret: config.SLACK_STATE_SECRET,
    processBeforeResponse: true,
    scopes: [
      "chat:write",
      "channels:join",
      "channels:history",
      "channels:read",
      "groups:read",
      "groups:history",
      "groups:read",
      "im:history",
      "mpim:history",
      "mpim:read",
      "reactions:read",
      "im:read"
    ],
    logLevel: LogLevel.DEBUG,
    installationStore: new MongoInstallationStore({
      model,
      orgMetaConfigModel
    }),
    installerOptions: {
      directInstall: true,
      installPathOptions: {
        beforeRedirection: async (req, res, opts) => {
          ---
          return true;
        }
      },
      callbackOptions: {
        beforeInstallation: async (opts, req, res) => {
          ----
          return true;
        },
        afterInstallation: async (installation, opts, req, res) => {
          console.log("[SLACK] afterInstallation", installation);
          ---
          return true;
        }
      }
    },
    dispatchErrorHandler: async ({ error, logger, response }) => {
      console.log("[SLACK] Error in dispatch", error);
      CatchError.captureException(`dispatch error: ${error}`);
      response.writeHead(404);
      response.write("Something is wrong!");
      response.end();
    },
    processEventErrorHandler: async ({ error, logger, response }) => {
      console.log("[SLACK] Error in processEvent", error);
      CatchError.captureException(`processEvent error: ${error}`);
      // acknowledge it anyway!
      response.writeHead(200);
      response.end();
      return true;
    },
    unhandledRequestHandler: async ({ logger, response }) => {
      console.log("[SLACK] Unhandled Request");
      CatchError.captureException(
        "Acknowledging this incoming request because 2 seconds already passed..."
      );
      // acknowledge it anyway!
      response.writeHead(200);
      response.end();
    }
  });

Serverless Start Code

import serverlessExpress from "@vendia/serverless-express";

let serverlessExpressInstance;

const startServerlessExpress = async (event, context, callback) => {
  try {
    console.log(
      "[SERVERLESS] Starting Serverless Express with event",
      event,
      context
    );
    const { receiver } = await init();
    //@ts-ignore
    serverlessExpressInstance = serverlessExpress({
      app: receiver.app,
      eventSourceRoutes: {
        AWS_SNS: "/sns"
      },
      logSettings: {
        level: "debug"
      }
    });

    return serverlessExpressInstance(event, context);
  } catch (e) {
    console.log("[SERVERLESS] Error Occurred", e);
    CatchError.captureException(e, {
      data: {
        message:
          "[SERVERLESS] Error Occurred in installation / events handler of Slack"
      }
    });
    callback(e);
  }
};

I also have a slack app initialised for registering listeners, but I dont think this is triggered in OAuth Flow

  const app = new SlackApp({
    signingSecret: config.SLACK_SIGNING_SECRET,
    clientId: config.SLACK_CLIENT_ID,
    clientSecret: config.SLACK_CLIENT_SECRET,
    receiver,
    port: 3001,
    processBeforeResponse: true,
    extendedErrorHandler: true
  });
  
  const ErrorHandler: ExtendedErrorHandler = async ({
    error,
    context,
    body
  }) => {
    console.log("[SLACK] Error occurred in slack app", error);
    throw error;
  };

  app.error(ErrorHandler); 

daga-segwise avatar Jan 05 '24 06:01 daga-segwise

@daga-segwise This could be indeed confusing, but for OAuth flow error patterns, you can use callbackOptions for it: https://slack.dev/node-slack-sdk/oauth#persisting-data-during-the-oauth-flow The event process error handlers work only for /slack/events requests.

seratch avatar Jan 08 '24 00:01 seratch

Hey Thanks for the response! I am using callback options, but I dont think this case reaches there. It sends an error before triggering any of the callback functions.

daga-segwise avatar Jan 08 '24 05:01 daga-segwise

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

github-actions[bot] avatar Feb 12 '24 00:02 github-actions[bot]

As this issue has been inactive for more than one month, we will be closing it. Thank you to all the participants! If you would like to raise a related issue, please create a new issue which includes your specific details and references this issue number.

github-actions[bot] avatar Feb 26 '24 00:02 github-actions[bot]