Botframework如何先进行身份验证,然后使用令牌进行图形api调用

问题描述 投票:0回答:1

验证对话框:

import { ChoicePrompt, DialogSet, DialogTurnStatus, OAuthPrompt, TextPrompt, WaterfallDialog, ComponentDialog } from 'botbuilder-dialogs';
import GraphClient from '../graph-client';

const MAIN_WATERFALL_DIALOG = 'mainWaterfallDialog';
const OAUTH_PROMPT = 'oAuthPrompt';
const CHOICE_PROMPT = 'choicePrompt';
const TEXT_PROMPT = 'textPrompt';
import moment = require('moment');

class AuthDialog extends ComponentDialog {
    constructor() {
        super('AuthDialog');
        this.addDialog(new ChoicePrompt(CHOICE_PROMPT))
            .addDialog(new OAuthPrompt(OAUTH_PROMPT, {
                connectionName: process.env.ConnectionName,
                text: 'Please login',
                title: 'Login',
                timeout: 300000
            }))
            .addDialog(new TextPrompt(TEXT_PROMPT))
            .addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
                this.promptStep.bind(this),
                this.processStep.bind(this)
            ]));

        this.initialDialogId = MAIN_WATERFALL_DIALOG;
    }

    /**
     * The run method handles the incoming activity (in the form of a TurnContext) and passes it through the dialog system.
     * If no dialog is active, it will start the default dialog.
     * @param {*} turnContext
     * @param {*} accessor
     */
    public async run(turnContext, accessor) {
        const dialogSet = new DialogSet(accessor);
        dialogSet.add(this);

        const dialogContext = await dialogSet.createContext(turnContext);
        const results = await dialogContext.continueDialog();
        if (results.status === DialogTurnStatus.empty) {
            await dialogContext.beginDialog(this.id);
        }
    }

    public async promptStep(step) {
        return step.beginDialog(OAUTH_PROMPT);
    }

    public async processStep(step) {
        if (step.result) {
            // We do not need to store the token in the bot. When we need the token we can
            // send another prompt. If the token is valid the user will not need to log back in.
            // The token will be available in the Result property of the task.
            const tokenResponse = step.result;
            // If we have the token use the user is authenticated so we may use it to make API calls.
            if (tokenResponse && tokenResponse.token) {
                await step.context.sendActivity(`Logged in.`);
            } else {
                await step.context.sendActivity('something wrong happened.');
            }
        } else {
            await step.context.sendActivity('We couldn\'t log you in. Please try again later.');
        }

        return await step.endDialog();
    }
}

export default AuthDialog;

我有一个连接到luis的主目录,并根据识别的意图执行相应的代码:

例如,在某些情况下,我拥有这个:

case 'CalendarEvents':
                return stepContext.beginDialog('AuthDialog');
                const calendar = await new GraphClient('token').events();
                let eventsBuilder: string = '';
                // tslint:disable-next-line: prefer-for-of
                for (let index = 0; index < calendar.length; index++) {
                    const element = calendar[index];
                    eventsBuilder += '\r\n' + moment(element.start.dateTime).format('dddd, MMMM Do YYYY, h:mm:ss a') + ' - ' + element.subject;
                }
                await step.context.sendActivity(`${eventsBuilder}`);

因此,如果意图是CalendarEvents,则进行身份验证,然后进行一些图形API调用。

我目前遇到的问题是,对图形api的调用是在身份验证完成之前进行的,我希望第一个用户进行身份验证,然后接收一些令牌,然后使用该令牌来获取图形api的调用!

任何想法如何实现以上目标?

node.js botframework azure-bot-service
1个回答
0
投票

请参阅Graph Auth Sample。特别是

  1. 它在MainDialog中获得令牌:
return step.beginDialog(OAUTH_PROMPT);

[...]

if (step.result) {
    const tokenResponse = step.result;
    if (tokenResponse && tokenResponse.token) {
        const parts = (step.values.command || '').toLowerCase().split(' ');

        const command = parts[0];

        switch (command) {
        case 'me':
            await OAuthHelpers.listMe(step.context, tokenResponse);
            break;
        case 'send':
            await OAuthHelpers.sendMail(step.context, tokenResponse, parts[1]);
            break;
        case 'recent':
            await OAuthHelpers.listRecentMail(step.context, tokenResponse);
            break;
        default:
            await step.context.sendActivity(`Your token is ${ tokenResponse.token }`);
        }
    }
}

[...]
  1. 然后,OAuthHelpers使用令牌:
static async sendMail(context, tokenResponse, emailAddress) {
    [...]
    const client = new SimpleGraphClient(tokenResponse.token);
    const me = await client.getMe();

    await client.sendMail(
        emailAddress,
        'Message from a bot!',
        `Hi there! I had this message sent from a bot. - Your friend, ${ me.displayName }`
    );
    await context.sendActivity(`I sent a message to ${ emailAddress } from your account.`);
}

这是示例的工作方式。对您来说,由于只想在Auth对话框中进行身份验证,因此需要使用Auth对话框从用户那里获取令牌,然后将其保存到其UserState中,类似于this sample。然后,您可以在任何对话框中检索其UserState并使用令牌(如果有)。

注意

您可以通过常规HTTP REST API请求使用Graph API,也可以像示例一样使用Graph SDK

© www.soinside.com 2019 - 2024. All rights reserved.