0

我一直在努力解决我附加到 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”添加到标识中。

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

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")}));
    };
}

不起作用。需要明确的是,它不会出错,但是在方法完成后,身份上不存在附加声明......

据我所知,通过消除各种事物,等待它打破的是等待,但 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 )并在 Startup.cs 中添加了 MicrosoftIdentityOptions 的自定义:(https ://github.com/VaticanUK/msal_so_fail_example/blob/master/Startup.cs#L40)使用文档中显示的模式:https ://github.com/AzureAD/microsoft-identity-web/wiki/customization#customization -in-the-startupcs

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

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

抛出异常,登录中止

如果添加 async 关键字,异常不会阻止登录: 抛出异常,但登录成功

4

1 回答 1

1

我在 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")}));
    };
}

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

于 2022-02-10T17:41:28.080 回答