MS小组Microsoft Bot身份验证V4

时间:2019-08-01 14:39:44

标签: c# authentication botframework microsoft-teams direct-line-botframework

我正在研究示例Bot Authentication MS GRAPH

我在仿真器通道中需要输出,如下图:

Emulator output

用户加入频道后,会向他显示欢迎消息和登录提示。身份验证对话框完成后,我想返回onMessageActivity继续执行我的代码。团队频道似乎根本不响应onMembersAdded

    protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in turnContext.Activity.MembersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    // First message and action that will happen when user joins the channel
                    await turnContext.SendActivityAsync(MessageFactory.Text("Welcome to Chat Bot. Please login."), cancellationToken);
                    // Call OAuthDialog
                    //await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
                    //  await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome to Audit Bot! I am happy to help!. Type 'Login' anytime to sign-in."), cancellationToken);


                }
            }
        }
        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext?.Activity?.Type == ActivityTypes.Invoke && turnContext.Activity.ChannelId == "msteams")
            {
                await turnContext.SendActivityAsync("You are using MS Teams.");
                await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
            }
            else
            {
                await base.OnTurnAsync(turnContext, cancellationToken);
                // Save any state changes that might have occured during the turn.
                await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
                await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
            }

        }
        protected override async Task OnTokenResponseEventAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Token Response Event Activity.");
            // Run the Dialog with the new Token Response Event Activity.
            // Create Token globally and assigned here
             token = turnContext.Activity.Value.ToString();
            //var myJsonString = "{token: {Id: \"aaakkj98898983\"}}";
            //var jo = JObject.Parse(token);
            // cToken = jo["token"].ToString();
            //  await turnContext.SendActivityAsync(cToken);
            await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);

        }
     protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
                // Call the MainDialog to display OAuth
                await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
                // Proceed with rest of the code
                Logger.LogInformation("Running dialog with Message Activity.");
                //  First, we use the dispatch model to determine which cognitive service(LUIS or QnA) to use.
                var recognizerResult = await _botServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);
                // Top intent tells us which cognitive service to use. LUIS or QnA Maker
                var topIntent = recognizerResult.GetTopScoringIntent();
                // Next, we call the dispatcher with the top intent.
                await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);      

        }

对话框类(我只想显示一次Graph调用)

 AddDialog(new OAuthPrompt(
            nameof(OAuthPrompt),
            new OAuthPromptSettings
            {
                ConnectionName = "my connection", // HARD CODED
                Text = "Please login",
                Title = "Login",
                Timeout = 300000, // User has 5 minutes to login
            }));

        AddDialog(new TextPrompt(nameof(TextPrompt)));
        //  AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));

        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {
                PromptStepAsync,
               LoginStepAsync

        }));

        // The initial child Dialog to run.
        InitialDialogId = nameof(WaterfallDialog);
    }

    private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        var tokenResponse = (TokenResponse)stepContext.Result;
        //Send token to state
        // stepContext.Context.TurnState.Add("tokenResponse", tokenResponse);

        if (tokenResponse != null)
        {
            ////
            await OAuthHelpers.ListMeAsync(stepContext.Context, tokenResponse);
            return await stepContext.EndDialogAsync();

        }
        else
        {
            return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);

        }

    }

    private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        // Get the token from the previous step. Note that we could also have gotten the
        // token directly from the prompt itself. There is an example of this in the next method.
        var tokenResponse = (TokenResponse)stepContext.Result;

        if (tokenResponse != null)
        {

            await stepContext.Context.SendActivityAsync(MessageFactory.Text("You are now logged in."), cancellationToken);
            // Display my name 
            await OAuthHelpers.ListMeAsync(stepContext.Context, tokenResponse);
            // End and return to the bot onMessageActivity
            return await stepContext.EndDialogAsync();

        }

        await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
        return await stepContext.EndDialogAsync();


    }

1 个答案:

答案 0 :(得分:1)

当用户首次添加漫游器时,团队只会在一次{strong>一次事件中触发OnMembersAdded事件。用户可以删除或卸载该漫游器,并且它将永远不会再次触发,而不仅仅是在初始时间。 注意:Facebook频道也是如此

相反,您要在两个页面上都触发OAuthPrompt对话框:

  1. OnMembersAdded(您已经这样做了),然后再次进入
  2. OnMessage(需要在此处添加await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(OAuthPrompt)), cancellationToken);

如果用户已经通过验证,则OAuthPrompt将返回令牌,而无需再次请求。您只需要确保您的OAuthPrompt对话框适当地处理已通过身份验证的用户即可。无论如何,最好在OnMessage中使用它,以确保您始终通过机器人进行身份验证。

我知道,这会使调试变得困难。您可以通过my answer here解决此问题,这是我今天回答的类似问题。