suttna/botbuilder-slack

Slack Examples cannot be installed

martibi opened this issue · 10 comments

Both the express and restify examples cannot be installed into a Slack workspace using Slack Button. Slack Button generates the following:

https://slack.com/oauth/authorize?scope=bot&client_id=client_id

After the above is called, and the authorization is given, the OAuth process fails with the following output:

Bot is listening...
error: Response not OK:  missing_scope

@martibi Hello!

Are you sure that bot is the only scope your bot uses ? Can you verify that ?

Yes I am using both the examples in your project https://github.com/suttna/botbuilder-slack/tree/master/example/src

The OAuth process tries to install the bot but the URL gets redirected to onOAuthErrorRedirectUrl.

I modified the example bot to use the function below instead of listenOAuth()and it works, so there is something wrong with botbuilder-slack's listenOAuth function:

// This route handles get request to a /oauth endpoint. We'll use this endpoint for handling the logic of the Slack oAuth process behind our app.
app.get('/slack/oauth', function(req, res) {
  // When a user authorizes an app, a code query parameter is passed on the oAuth endpoint. If that code is not there, we respond with an error message
  if (!req.query.code) {
      res.status(500);
      res.send({"Error": "Looks like we're not getting code."});
      console.log("Looks like we're not getting code.");
  } else {
      // If it's there...

      // We'll do a GET call to Slack's `oauth.access` endpoint, passing our app's client ID, client secret, and the code we just got as query parameters.
      request({
          url: 'https://slack.com/api/oauth.access', //URL to hit
          qs: {code: req.query.code, client_id: process.env.SLACK_CLIENT_ID, 
               client_secret: process.env.SLACK_CLIENT_SECRET}, //Query string data
          method: 'GET', //Specify the method

      }, function (error, response, body) {
          if (error) {
              console.log(error);
          } else {
              res.json(body);

          }
      })
  }
});

@martibi Can you show the code you are using and a screenshot of the slack permissions page ? That will help us troubleshoot a potential issue.

  1. I'm using the examples in your botbuilder-slack project. I did not modify anything.
  2. I just did one small modification to package.json to use botbuilder-slack directly:
{
  "dependencies": {
    "botbuilder-slack": "^2.0.0"
  }
}
  1. Started ngrok with ngrok http 1234 to obtain ngrok address.
  2. Added Slack application, and Slack bot user named "botbuilder".
  3. Obtained the CLIENT_ID, CLIENT_SECRET from Slack.
  4. Setup OAuth Redirect URL on Slack to point to ngrok address:

slack oauth

  1. Setup OAuth Scope:

slack oauth2

  1. Install this Slack App and authorize it.

  2. Next I started the express example with this script:

#!/bin/bash
export SLACK_BOT_NAME="botbuilder"
export SLACK_VERIFICATION_TOKEN="xyz"
export SLACK_CLIENT_ID="xyz"
export SLACK_CLIENT_SECRET="xyz"
export SLACK_OAUTH_REDIRECT_URL="https://foobar.ngrok.io/slack/oauth" #matched to ngrok address obtained above
export SLACK_OAUTH_ON_SUCCESS_REDIRECT_URL="https://example.com/success"
export SLACK_OAUTH_ON_ERROR_REDIRECT_URL="https://example.com/error"
export SLACK_OAUTH_ON_ACCESS_DENIED_REDIRECT_URL="https://example.com/redirect"
export PORT=1234

npx ts-node src/express.ts
  1. Proceed to https://api.slack.com/docs/slack-button and selected this app and "commands, bot".
  2. Click on "Add to Slack" button.
  3. Output is shown:
error: Response not OK:  missing_scope

As mentioned, after I modified the express.ts to the following the installation from "Add to Slack" button worked:

import * as express from "express"
import * as bodyParser from "body-parser"
import { SlackConnector } from "botbuilder-slack"
import { createBot, BotCache } from "./bot"
import * as request from "request"

const port = process.env.PORT || 3000
const botsCache: BotCache = {}

const connectorSettings = {
  botLookup: (teamId: string) => {
    const botEntry = botsCache[teamId]

    if (botEntry) {
      return Promise.resolve([botEntry.token, botEntry.identity.id] as [string, string])
    } else {
      return Promise.reject(new Error('Bot not found'))
    }
  },
  botName: process.env.SLACK_BOT_NAME,
  verificationToken: process.env.SLACK_VERIFICATION_TOKEN,
  clientId: process.env.SLACK_CLIENT_ID,
  clientSecret: process.env.SLACK_CLIENT_SECRET,
  redirectUrl: process.env.SLACK_OAUTH_REDIRECT_URL,
  onOAuthSuccessRedirectUrl: process.env.SLACK_OAUTH_ON_SUCCESS_REDIRECT_URL,
  onOAuthErrorRedirectUrl: process.env.SLACK_OAUTH_ON_ERROR_REDIRECT_URL,
  onOAuthAccessDeniedRedirectUrl: process.env.SLACK_OAUTH_ON_ACCESS_DENIED_REDIRECT_URL
}

const connector = new SlackConnector(connectorSettings)

const app = express()

app.use(bodyParser.json())
app.use(bodyParser.urlencoded())

app.listen(port, () => {
  console.log(`Bot is listening on port ${port}`)
})

// This route handles get request to a /oauth endpoint. We'll use this endpoint for handling the logic of the Slack oAuth process behind our app.
app.get('/slack/oauth', function(req, res) {
  // When a user authorizes an app, a code query parameter is passed on the oAuth endpoint. If that code is not there, we respond with an error message
  if (!req.query.code) {
      res.status(500);
      res.send({"Error": "Looks like we're not getting code."});
      console.log("Looks like we're not getting code.");
  } else {
      // If it's there...

      // We'll do a GET call to Slack's `oauth.access` endpoint, passing our app's client ID, client secret, and the code we just got as query parameters.
      request({
          url: 'https://slack.com/api/oauth.access', //URL to hit
          qs: {code: req.query.code, client_id: process.env.SLACK_CLIENT_ID, 
               client_secret: process.env.SLACK_CLIENT_SECRET}, //Query string data
          method: 'GET', //Specify the method

      }, function (error, response, body) {
          if (error) {
              console.log(error);
          } else {
              res.json(body);

          }
      })
  }
});

app.post('/slack/events', connector.listenEvents())
app.post('/slack/interactive', connector.listenInteractiveMessages())
app.post('/slack/command', connector.listenCommands())
//app.get('/slack/oauth', connector.listenOAuth())

createBot(connector, botsCache)

@martibi What version of botbuilder are you using ? Can you show the url that the Slack Button redirects you please ?

Thanks

I am using botbuilder 3.9.1 as in the example, but when I updated to 3.15.1 the error still occurs.

The URL that is being redirected by the Slack Button is: https://slack.com/oauth/authorize?scope=commands,bot&client_id=xyzabc

Can you try changing scope=commands,bot for scope=commands+bot ?

Using scope=commands+bot returns the same error:

error: Response not OK:  missing_scope

Error: missing_scope
    at handleHttpResponse (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/call-transport.js:103:17)
    at handleTransportResponse (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/call-transport.js:153:19)
    at apply (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:478:17)
    at wrapper (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:5323:16)
    at Request.handleRequestTranportRes (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/request.js:21:5)
    at apply (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:478:17)
    at Request.wrapper [as _callback] (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:5323:16)
    at Request.self.callback (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:186:22)
    at Request.emit (events.js:182:13)
    at Request.EventEmitter.emit (domain.js:442:20)
    at Request.<anonymous> (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:1060:10)
    at Request.emit (events.js:182:13)
    at Request.EventEmitter.emit (domain.js:442:20)
    at IncomingMessage.<anonymous> (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:980:12)
    at Object.onceWrapper (events.js:273:13)
    at IncomingMessage.emit (events.js:187:15) 'Error: missing_scope\n    at handleHttpResponse (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/call-transport.js:103:17)\n    at handleTransportResponse (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/call-transport.js:153:19)\n    at apply (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:478:17)\n    at wrapper (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:5323:16)\n    at Request.handleRequestTranportRes (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/lib/clients/transports/request.js:21:5)\n    at apply (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:478:17)\n    at Request.wrapper [as _callback] (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/lodash/lodash.js:5323:16)\n    at Request.self.callback (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:186:22)\n    at Request.emit (events.js:182:13)\n    at Request.EventEmitter.emit (domain.js:442:20)\n    at Request.<anonymous> (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:1060:10)\n    at Request.emit (events.js:182:13)\n    at Request.EventEmitter.emit (domain.js:442:20)\n    at IncomingMessage.<anonymous> (botbuilder-slack/example/node_modules/botbuilder-slack/node_modules/@slack/client/node_modules/request/request.js:980:12)\n    at Object.onceWrapper (events.js:273:13)\n    at IncomingMessage.emit (events.js:187:15)'