问题
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