How to Implement OAuth Prompt Authentication for Virtual Assistant Bot with Skills

血红的双手。 提交于 2020-01-24 13:08:05

问题


I followed step-by-step docs to add authentication to a sample skill as part of a virtual assistant bot created via the Virtual Assistant Template.

I have created an Azure Active Directory V2 app registration for the skill and added an OAuth connection linked to that app in the skill bot in Azure portal. I have also updated OAuthConnections in appsettings.json of the skill.

appsettings.json

  "oauthConnections": [
    {
      "name": "calendarconnection",
      "provider": "Azure Active Directory v2"
    }
    . . .

But I am stuck on how to implement the OAuth prompt flow for the user to log in to the skill from the virtual assistant, since the virtual assistant template is built in a specific way, i.e. MainDialog inherits from RouterDialog.

public class MainDialog : RouterDialog
{
    public MainDialog(
            BotSettings settings,
            BotServices services,
            OnboardingDialog onboardingDialog,
            EscalateDialog escalateDialog,
            CancelDialog cancelDialog,
            List<SkillDialog> skillDialogs,
            IBotTelemetryClient telemetryClient,
            UserState userState)
            : base(nameof(MainDialog), telemetryClient)
    {
        . . .
    }

    . . .

    protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
    {
        . . .
    }
    . . .
    protected override async Task<InterruptionAction> OnInterruptDialogAsync(DialogContext dc, CancellationToken cancellationToken)
    {
        . . .
    }
    . . .

What would I need to do differently from the code shown in the step-by-step docs in this case?

UPDATE: I added a new dialog LoginDialog and launched it from OnStartAsync

MainDialog.cs

        public MainDialog(
            BotSettings settings,
            BotServices services,
            ResponseManager responseManager,
            ConversationState conversationState,
            UserState userState,
            ProactiveState proactiveState,
            CreateEventDialog createEventDialog,
            ChangeEventStatusDialog changeEventStatusDialog,
            TimeRemainingDialog timeRemainingDialog,
            SummaryDialog summaryDialog,
            UpdateEventDialog updateEventDialog,
            ConnectToMeetingDialog connectToMeetingDialog,
            UpcomingEventDialog upcomingEventDialog,
            LoginDialog loginDialog,               // added
            OAuthPrompt oAuthPrompt,               // added
            ConfirmPrompt confirmPrompt,           // added
            IBotTelemetryClient telemetryClient)
            : base(nameof(MainDialog), telemetryClient)
        {
            _settings = settings;
            _services = services;
            . . .

            AddDialog(loginDialog);
            AddDialog(oAuthPrompt);
            AddDialog(confirmPrompt);

        }
        . . .
        protected override async Task OnStartAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            await dc.BeginDialogAsync(nameof(LoginDialog));
            // send a greeting if we're in local mode
            await dc.Context.SendActivityAsync(_responseManager.GetResponse(CalendarMainResponses.CalendarWelcomeMessage));
        }
        . . .

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
 . . .
     services.AddTransient<LoginDialog>();
     services.AddTransient<OAuthPrompt>();
     services.AddScoped<ConfirmPrompt>(_ => new ConfirmPrompt(nameof(ConfirmPrompt)));
     services.AddScoped<OAuthPrompt>(_ => new OAuthPrompt(nameof(OAuthPrompt), new OAuthPromptSettings { ConnectionName = "calendarconnection", Title = "Sign In" }));
 . . .
}

LoginDialog.cs

public class LoginDialog : ComponentDialog
{
    public LoginDialog() 
        : base(nameof(LoginDialog))
    {
        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {
            PromptStepAsync,
            LoginStepAsync,
            DisplayTokenPhase1Async,
            DisplayTokenPhase2Async

         }));
    }

    private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)

    {

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

    }
    . . .
}

The biggest issue here is that I am still being asked to sign in after I already signed in. Note also that the third OAuth prompt is different which is why I get the following error when I click on it.

Code: InvalidAuthenticationToken Message: CompactToken parsing failed with error code: 80049217

Inner error

This is where the exception occurs in the code:

MSGraphCalendarAPI.cs

private async Task<List<Event>> GetMyCalendarViewByTime(DateTime startTime, DateTime endTime)
{
      . . .
      try
      {
           events = await _graphClient.Me.CalendarView.Request(options).GetAsync();
      }
      catch (ServiceException ex)
      {
           throw GraphClient.HandleGraphAPIException(ex);
      }
      . . .
}

来源:https://stackoverflow.com/questions/57466203/how-to-implement-oauth-prompt-authentication-for-virtual-assistant-bot-with-skil

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!