【问题标题】:MS teams Microsoft Bot Authentication V4MS 团队 Microsoft Bot Authentication V4
【发布时间】:2019-08-12 21:38:57
【问题描述】:

我正在研究示例Bot Authentication MS GRAPH

我在仿真器通道中有所需的输出,如下图所示:

当用户加入频道时,他会看到欢迎消息和登录提示。身份验证对话框完成后,我想返回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);      

        }

Dialog 类(我只想显示一次 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();


    }

【问题讨论】:

  • 所以你的问题是?该事件永远不会被抛出,并且您不会在 Teams 频道中获得登录请求,对吧?
  • 我查看了您添加的代码,没有发现任何问题。它可能与“精简”登录提示有关。你可以添加那个代码吗?老实说,如果您可以链接到代码的存储库或将其压缩并通过电子邮件发送,我可以更轻松地提供帮助。 vDAHmicricATmicrosoftDOTcom(用适当的字符替换大写)

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


【解决方案1】:

团队只会触发OnMembersAdded 事件一次 次 -- 当用户首次添加机器人时。用户可以删除或卸载机器人,但它仍然不会再次触发,而不仅仅是最初的时间。 注意:Facebook 频道也是这样的

您想要做的是在两者上触发OAuthPrompt 对话框:

  1. OnMembersAdded(你已经这样做了),然后再次进入
  2. OnMessage(需要在这里添加await Dialog.RunAsync(turnContext, ConversationState.CreateProperty&lt;DialogState&gt;(nameof(OAuthPrompt)), cancellationToken);

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

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

【讨论】:

  • 您好,感谢您的回复。我已经在 onMessageActivity 中添加了这行代码,但我现在遇到的问题是,每次我问机器人问题时,该方法都会一直显示对话框消息以及我自己的代码。这可能是指 OAuthPrompt 处理经过身份验证的用户。我已经尝试了一些 if else 语句检查令牌是否存在等,但我仍然得到同样的错误。
  • @Rikardo 很难确切地说出是什么原因造成的,因为很多不同地方的代码都可能发生这种情况,主要是OnMessageOnTurnOnMembersAdded 和您的整个对话框。您能否在您的问题中包含指向您的代码的链接或将所有这些链接编辑到您的问题中?
  • 我已经用代码更新了第一篇文章中的代码。我已经设法让 onMembers 解决这个问题,就像你说的那样,它只发生一次。我现在遇到的问题是检查用户是否经过身份验证。如果它不显示消息“您现在已登录”,而是在 onMessageActivity 中执行我自己的代码。我现在遇到的问题是我自己的来自 bot 类和对话框类的代码在我发送消息时一直在运行。有什么帮助吗?
  • @Rikardo Auth 对话框应该与每条消息一起运行,以确保用户已通过身份验证。要阻止它显示消息,只需在随后调用对话框时删除该行。尝试调整对话代码流,如果遇到问题,请打开一个新的 Stack Overflow 问题。
  • @Rikardo 任何更新,我都面临同样的问题。当我对发送到机器人的每条消息运行 OAuthPrompt 对话框时,它会运行 OAuthPrompt 对话框 + 我要为 OnMessageActivityAsync 执行的代码。并且找不到解决方法来检查用户是否已登录并在没有运行 OAuthPrompt 对话框的情况下继续我的执行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 2019-04-22
  • 2018-01-27
  • 1970-01-01
  • 2018-12-29
  • 1970-01-01
  • 2019-09-30
相关资源
最近更新 更多