Microsoft.Identity.Web OnTokenValidated 事件似乎不能很好地处理异步

Microsoft.Identity.Web OnTokenValidated event doesn't seem to play nicely with async

我一直在努力解决我附加到 OnTokenValidated 的 Func 没有做它应该做的事情。

经过大量尝试不同的事情:

services.Configure<MicrosoftIdentityOptions>(options =>
{
    options.Events ??= new OpenIdConnectEvents();
    options.Events.OnTokenValidated += context =>
    {
        context.Principal.AddIdentity(new ClaimsIdentity(new List<Claim> {new Claim("Foo", "Bar")}));
        return Task.CompletedTask;
    };
}

按预期工作,并将值为“Bar”的声明“Foo”添加到标识中。

但是,一旦我在代码中等待任务并使函数异步,附加声明就不会添加到已登录的身份中:

services.Configure<MicrosoftIdentityOptions>(options =>
{
    options.Events ??= new OpenIdConnectEvents();
    options.Events.OnTokenValidated += async context =>
    {
        var someService = context.HttpContext.RequestServices.GetRequiredService<ISomeService>();
        var someValue = await someService.SomeMethod();
        context.Principal.AddIdentity(new ClaimsIdentity(new List<Claim> {new Claim("Foo", "Bar")}));
    };
}

不起作用。要清楚,它没有错误,但是在该方法完成后,身份上不存在附加声明...

据我所知,通过消除各种因素,是 await 导致它中断,但 OnTokenValidated 的定义是:

Func<TokenValidatedContext,Task> OnTokenValidated

所以似乎期望处理程序是异步的?


更新:2022-02-07 更进一步:

OnTicketReceived = ctx =>
{
    throw new AuthenticationException("Sorry, you cannot log in");
}

由于抛出异常导致登录失败,而

OnTicketReceived = async ctx =>
{
    throw new AuthenticationException("Sorry, you cannot log in");
}

不起作用 - 抛出的异常不影响登录,尽管抛出异常,用户仍正确登录。看起来好像代码执行已经继续进行,好像堆栈中某处的某些东西没有等待......但是查看 github 上的代码我找不到堆栈中异步方法的任何地方'等待


更新2022-02-09 例子: https://github.com/VaticanUK/msal_so_fail_example

我已经采用了官方 MS 示例之一(可在此处获取:https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2) and added the customisation of MicrosoftIdentityOptions in Startup.cs: (https://github.com/VaticanUK/msal_so_fail_example/blob/master/Startup.cs#L40) using the pattern shown in the documentation: https://github.com/AzureAD/microsoft-identity-web/wiki/customization#customization-in-the-startupcs

以运行为例,您需要在Azure中创建一个应用程序并在appsettings.json中设置您的客户端ID。

按原样,该示例将起作用,我的意思是登录将失败(因为没有 async 关键字):

如果加上async关键字,异常不会阻止登录:

我在 MSAL Github 帐户上提出了上述问题,在与其中一位贡献者聊天后,答案是在注册包含事件处理程序的选项时,它需要注册为:

services.Configure<MicrosoftIdentityOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>

而不是:

services.Configure<MicrosoftIdentityOptions>(options =>

所以有效的完整注册是:

services.Configure<MicrosoftIdentityOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Events ??= new OpenIdConnectEvents();
    options.Events.OnTokenValidated += async context =>
    {
        var someService = context.HttpContext.RequestServices.GetRequiredService<ISomeService>();
        var someValue = await someService.SomeMethod();
        context.Principal.AddIdentity(new ClaimsIdentity(new List<Claim> {new Claim("Foo", "Bar")}));
    };
}

目前,我不明白这是如何解决问题的,或者为什么不将身份验证方案作为注册名称会导致它只能同步工作,但它解决了我的问题,所以我可能会出于求知欲尝试弄清真相,但以上解决了眼前的问题!