C# 如何用技巧实现虚拟助手Bot的OAuth提示认证
随后,我将身份验证添加到,作为通过创建的虚拟助手bot的一部分 我已经为该技能创建了Azure Active Directory V2应用程序注册,并在Azure门户中的技能机器人中添加了链接到该应用程序的OAuth连接。我还更新了技能的appsettings.json中的OAuthConnections appsettings.jsonC# 如何用技巧实现虚拟助手Bot的OAuth提示认证,c#,azure,oauth-2.0,azure-active-directory,botframework,C#,Azure,Oauth 2.0,Azure Active Directory,Botframework,随后,我将身份验证添加到,作为通过创建的虚拟助手bot的一部分 我已经为该技能创建了Azure Active Directory V2应用程序注册,并在Azure门户中的技能机器人中添加了链接到该应用程序的OAuth连接。我还更新了技能的appsettings.json中的OAuthConnections appsettings.json "oauthConnections": [ { "name": "calendarconnection", "provid
"oauthConnections": [
{
"name": "calendarconnection",
"provider": "Azure Active Directory v2"
}
. . .
但我一直在讨论如何实现OAuth提示流,以便用户从虚拟助手登录到技能,因为虚拟助手模板是以特定的方式构建的,即MainDialog继承自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)
{
. . .
}
. . .
Startup.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));
}
. . .
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" }));
. . .
}
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);
}
. . .
}
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);
}
. . .
}
public void配置服务(IServiceCollection服务)
{
. . .
services.AddTransient();
services.AddTransient();
AddScoped(=>newconfirmport(nameof(confirmport));
addScope(=>newOAuthPrompt(nameof(OAuthPrompt),newOAuthPromptSettings{ConnectionName=“calendarconnection”,Title=“Sign-In”}));
. . .
}
LoginDialog.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));
}
. . .
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" }));
. . .
}
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);
}
. . .
}
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);
}
. . .
}
public类LoginDialog:ComponentDialog
{
公共后勤
:base(name of(LoginDialog))
{
AddDialog(新建WaterWallDialog)(名称(WaterWallDialog),新建WaterWallStep[]
{
PromptStepAsync,
LoginStepAsync,
DisplayTokenPhase1Async,
DisplayTokenPhase2Async
}));
}
专用异步任务PromptStepAsync(WaterWallStepContext stepContext,CancellationToken CancellationToken)
{
返回wait-stepContext.BeginDialogAsync(nameof(OAuthPrompt),null,cancellationToken);
}
. . .
}
这里最大的问题是,在我已经登录后,仍有人要求我登录。还要注意的是,第三个OAuth提示符是不同的,这就是为什么我单击它时会出现以下错误。
代码:InvalidAuthenticationToken
消息:CompactToken解析失败,错误代码:80049217
内部误差
这是代码中发生异常的地方:
MSGraphCalendarAPI.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));
}
. . .
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" }));
. . .
}
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);
}
. . .
}
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);
}
. . .
}
private异步任务GetMyCalendarViewByTime(DateTime startTime,DateTime endTime)
{
. . .
尝试
{
events=await_graphClient.Me.CalendarView.Request(options).GetAsync();
}
捕获(ServiceException ex)
{
抛出GraphClient.HandleGraphApieException(ex);
}
. . .
}
你能在appsettings.json中发布你是如何配置oauthConnections的吗?我已经更新了帖子。oauthConnections看起来不错。你能发布你到目前为止尝试过的内容吗?我已经更新了我尝试过的内容。错误是从Microsoft Graph API返回的。我建议解析令牌,看看它是否有问题。你能试着在这里解析它吗?同时,我会看一看你的更新代码,然后再继续。