Проверка блокировки с помощью Oauth

#authentication #oauth-2.0 #slack #slack-api #slack-commands

#аутентификация #oauth-2.0 #слабость #slack-api #slack-команды

Вопрос:

Я уже пару дней пытаюсь разобраться с этим. У меня есть приложение slack, работающее в разработке с использованием Slack / Bolt и встроенного экспресс-сервера. В процессе разработки я могу успешно пройти процесс установки, который по завершении возвращает учетные данные пользователя (токен аутентификации, идентификатор команды и т. Д.) И перенаправляет меня на мою страницу успеха. Кроме того, мои команды с косой чертой работают должным образом.

Однако в рабочей среде ни команда slash, ни процесс установки не работают. Команда slash возвращает ошибку «dispatch_failed» в Slack и следующую ошибку проверки в моих журналах:

ошибка в журналах сервера

Процесс установки в процессе разработки начинается с моей целевой страницы с кнопки добавления в slack, которая переводит меня на страницу slack, где я авторизую требуемые области. При отправке этой формы время ожидания моего приложения истекает с ошибкой 503. Я вижу «код» в URL, но он не обрабатывается. Прежде чем разорвать приложение на части, чтобы попробовать другой метод аутентификации, я надеялся, что кто-нибудь сможет определить, где я ошибся.

Важным является токен аутентификации. В процессе разработки я объявляю свой токен xbot при объявлении приложения. Я удаляю его для производства и передаю токены бота из контекстной переменной в прослушивателях событий (команда косой черты и т. Д.). Вот как я понял процесс из документации, но мог ошибаться…

 const { App, ExpressReceiver } = require('@slack/bolt');
require('dotenv').config({ path: __dirname   '/.env' })
const axios = require('axios')
const request = require('request')
const bodyParser = require('body-parser')
const path = require('path')
const firebase = require("firebase");

//database config here (removed to de-clutter)

const fetchTeam = async (teamId) => {
    try {
        const ref = await database.ref('workspaces')
        ref.orderByChild('team_id').equalTo(teamId).once('value', function (snapshot) {
            return snapshot.val()
        })
    } catch (e) {
        console.log(e);
    }
}

// Create a Bolt Receiver
const receiver = new ExpressReceiver({ signingSecret: process.env.SLACK_SIGNING_SECRET });

const app = new App({
    signingSecret: process.env.SLACK_SIGNING_SECRET,
    clientId: process.env.SLACK_CLIENT_ID,
    clientSecret: process.env.SLACK_CLIENT_SECRET,
    stateSecret: process.env.STATE_SECRET,
    scopes: ['chat:write', 'chat:write:bot', 'im:write', 'commands', 'incoming-webhook', 'users:read', 'users:read.email'],
    // scopes: ['chat:write', 'chat:write:bot', 'channels:history', 'groups:history', 'im:history', 'commands', 'incoming-webhook', 'users:read', 'users:read.email'],
    installationStore: {
        storeInstallation: async (installation) => {
            return await database.ref('workspaces').push({ team_id: installation.team.id, installation })
        },
        fetchInstallation: async (InstallQuery) => {
            return await fetchTeam(InstallationQuery.teamId)
        },
    },
    //removed token for production
    //token: process.env.SLACK_BOT_TOKEN,
    receiver
});

//a bunch of stuff my slack app does here (removed)


receiver.router.get('/slack/oauth_redirect', async (req, res) => {
    var options = {
        uri: 'https://slack.com/api/oauth.v2.access?code='
              req.query.code  
            'amp;client_id='   process.env.SLACK_CLIENT_ID  
            'amp;client_secret='   process.env.SLACK_CLIENT_SECRET,
        method: 'GET'
    }
    request(options, async (error, response, body) => {
        var JSONresponse = JSON.parse(body)
        if (!JSONresponse.ok) {
            res.status(500).send("Error: ", JSONresponse)
        } else {
            const newOBJ = {
                team_id: JSONresponse.team.id,
                ...JSONresponse
            }
            console.log(newOBJ);
            await database.ref('workspaces').push(newOBJ)
          
        }
    })
})


receiver.router.post('/', (req, res) => {
    const payload = JSON.parse(req.body.payload)
    res.send(req.data);
});

receiver.router.post('/slack/events', (req, res) => {
    res.send(req.data);
});

receiver.router.post('/actions', (req, res) => {
    res.send(req.data);
});

// Listen for a slash command invocation
app.command('/commandName', async ({ command, ack, say, context }) => {
    await ack();
    try {
        // Call the users.info method using the built-in WebClient
        const result = await app.client.users.info({
            token: context.botToken,
            //in development i use the code below
            // token: process.env.SLACK_BOT_TOKEN,
            user: user
        });
    }
    catch (error) {
        console.error(error);
    }

    await say({
        "blocks": [
            {
                "type": "section",
                "text": {
                    "type": "plain_text",
                    "text": `Hi there 👋,! Here are some ways you can use Slack to get things done with Webstacks:`,
                    "emoji": true
                }
            },
            {
                "type": "actions",
                "elements": [
                    {
                        "type": "button",
                        "text": {
                            "type": "plain_text",
                            "text": "Raise a Request"
                        },
                        "value": "create_request",
                        "action_id": "create_request"
                    },
                    {
                        "type": "button",
                        "text": {
                            "type": "plain_text",
                            "text": "Leave a Review",
                        },
                        "url": "https://kittycats.com"
                    }
                ]
            }
        ]
    })
});

(async () => {
    // Start your app
    await app.start(process.env.PORT || 3000);

    console.log('⚡️ Bolt app is running!');
})();  

Комментарии:

1. Когда происходит storeInstallation вызов? Зачем нам нужен ‘/slack/oauth_redirect, если storeInstallation может сделать это за нас?

2. @SagarRanglani storeInstallation вызывается только после того, как произойдет несколько событий. 1. Вы нажимаете «добавить в slack button» 2. Вы видите страницу OAuth, на которой написано: «Приложение запрашивает разрешение на доступ к рабочей области <demo> Slack. Нажмите зеленую кнопку «Разрешить». 3. Далее вы должны увидеть «Успех! Перенаправление» и предупреждение «Открыть Slack?» в вашем браузере. Нажмите «Открыть Slack» 4. Только после того, как вы успешно открыли Slack и перейдете на вкладку сообщений вашего приложения, функция «storeInstallation» действительно будет вызвана. Надеюсь, это поможет!

3. @HoreaPorutiu нужно ли нам устанавливать какой-либо URL-адрес события или какую-либо другую конфигурацию, а не код? Потому что установка хранилища не запускается с тем же кодом, что и в моем случае.

Ответ №1:

дважды проверьте переменные среды! 🙂 Я упустил из виду clientSecret, имеющий вход signingSecret