howdyai / botkit

Botkit is an open source developer tool for building chat bots, apps and custom integrations for major messaging platforms.
MIT License
11.49k stars 2.29k forks source link

Server Crash due to Missing Credentials in Slack Adapter #2246

Open bug-and-debug opened 8 months ago

bug-and-debug commented 8 months ago

Environment

Description

Our server experienced a crash on March 19, with the logs indicating an issue related to missing credentials for a team in the Slack adapter. This led to an uncaught exception, causing the server to move from an 'up' to 'crashed' state.

Error Logs

Mar 19 10:47:25 State changed from up to crashed
Mar 19 10:47:25 Team not found in userCache:  TXXXXXXN
Mar 19 10:47:25 Experienced an error inside the turn handler Error: Missing credentials for team.
Mar 19 10:47:25     at SlackAdapter.<anonymous> (/app/node_modules/botbuilder-adapter-slack/lib/slack_adapter.js:224:31)
Mar 19 10:47:25     at Generator.next (<anonymous>)
Mar 19 10:47:25     at fulfilled (/app/node_modules/botbuilder-adapter-slack/lib/slack_adapter.js:12:58)
Mar 19 10:47:25 node:internal/process/promises:279
Mar 19 10:47:25             triggerUncaughtException(err, true /* fromPromise */);
Mar 19 10:47:25             ^
Mar 19 10:47:25 Error: Missing credentials for team.
Mar 19 10:47:25     at SlackAdapter.<anonymous> (/app/node_modules/botbuilder-adapter-slack/lib/slack_adapter.js:224:31)
Mar 19 10:47:25     at Generator.next (<anonymous>)
Mar 19 10:47:25     at fulfilled (/app/node_modules/botbuilder-adapter-slack/lib/slack_adapter.js:12:58)
Mar 19 10:47:25 Process exited with status 1

Suspected Cause

The error Missing credentials for team suggests an issue with the way our bot is handling team credentials. It seems that the bot is trying to access credentials for a team that is not present in our cache.

Code Snippet

// adapter.ts
import {
  SlackAdapter,
  SlackEventMiddleware,
  SlackMessageTypeMiddleware,
} from 'botbuilder-adapter-slack';
import { BOT_SCOPE_LIST, SLACK_OAUTH_TOKEN } from '../../constants';

let tokenCache: any = {};
let userCache: any = {};

const getTokenForTeam = async (teamId: string): Promise<any> => {
  if (tokenCache[teamId]) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(tokenCache[teamId]);
      }, 150);
    });
  } else {
    console.error('Team not found in tokenCache: ', teamId);
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(null);
      }, 150);
    });
  }
};

const getBotUserByTeam = async (teamId: string): Promise<any> => {
  if (userCache[teamId]) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(userCache[teamId]);
      }, 150);
    });
  } else {
    console.error('Team not found in userCache: ', teamId);
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(null);
      }, 150);
    });
  }
};

export const configSlackBotAdapter = async () => {
  // A BotKit configuration
  const slackAdapter: SlackAdapter = new SlackAdapter({
    // auth token for a single-team app
    botToken: SLACK_OAUTH_TOKEN,

    // parameters used to secure webhook endpoint
    verificationToken: process.env.SLACK_BOT_VERIFICATION_TOKEN,
    clientSigningSecret: process.env.SLACK_BOT_CLIENT_SIGNING_SECRET,

    scopes: BOT_SCOPE_LIST,
    // credentials used to set up oauth for multi-team apps
    clientId: process.env.SLACK_BOT_CLIENT_ID,
    clientSecret: process.env.SLACK_BOT_CLIENT_SECRET,
    redirectUri: process.env.SLACK_BOT_REDIRECT_URI,
    getTokenForTeam: getTokenForTeam,
    getBotUserByTeam: getBotUserByTeam,
    oauthVersion: 'v2',
  });

  // Use SlackEventMiddleware to emit events that match their original Slack event types.
  slackAdapter.use(new SlackEventMiddleware());

  // Use SlackMessageType middleware to further classify messages as direct_message,
  // direct_mention, or mention
  slackAdapter.use(new SlackMessageTypeMiddleware());

  return slackAdapter;
};

Requested Assistance

We are looking for help in identifying the root cause of this crash and suggestions on how to prevent this issue in the future. Specifically:

  1. Insights on why the Missing credentials for team error might be occurring.
  2. Best practices for managing credentials and caching in a Slack bot environment.
  3. Any recommended code changes or updates to handle this scenario better.
  4. The server should not crash due to missing credentials and should handle such exceptions gracefully.

Any insights or suggestions to prevent such crashes in the future would be greatly appreciated.