【问题标题】:Specify JWT authentication scheme per request为每个请求指定 JWT 身份验证方案
【发布时间】:2020-06-06 21:43:44
【问题描述】:

我有一个 Web 应用程序,它为无限数量的 B2C 租户实施基于 Azure B2C 的身份验证。应用程序在运行时根据主机子域设置上下文,然后选择适当的租户。

这在客户端很容易工作,因为应用程序只在任何给定时间在单一上下文下在用户浏览器上运行。但是,由于 API 层只有一个实例,因此它必须能够同时支持来自多个不同用户的请求,这些请求使用由多个不同租户发布的不记名令牌。

我使用以下代码在启动时为每个租户添加身份验证方案。方案名称等于源上下文的url:

        foreach (Context context in Contexts)
        {

            services.AddAuthentication()
            .AddJwtBearer(context.url,
                jwtOptions =>
                {
                    jwtOptions.Authority = context.tenant;
                    jwtOptions.Audience = context.client;
                }
            );

        }

我的问题是,我如何告诉身份验证中间件使用哪种方案来验证用户的不记名令牌?有没有办法自动发生这种情况,还是我需要创建一个自定义 AuthorizeAttribute?

谢谢!

更新:我可以通过创建和注册自定义策略提供程序来实现此功能,如下所示:

internal class MyCustomPolicyProvider : IAuthorizationPolicyProvider
{

    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyCustomPolicyProvider(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
    {
        Uri uri = new Uri(_httpContextAccessor.HttpContext.Request.Headers["Referer"].ToString());
        return Task.FromResult(new AuthorizationPolicyBuilder(uri.Host).RequireAuthenticatedUser().Build());
    }


    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        Uri uri = new Uri(_httpContextAccessor.HttpContext.Request.Headers["Referer"].ToString());
        return Task.FromResult(new AuthorizationPolicyBuilder(uri.Host).RequireAuthenticatedUser().Build());
    }

}

然后控制器像这样受到保护:

[Authorize(Policy = "MyCustom")]

这感觉有点笨拙,但确实有效。我不太明白的一件事是为什么 IAuthorizationPolicyProvider 所需的 GetPolicyAsync() 和 GetDefaultPolicyAsync() 都在每个授权上运行。看来我们应该只需要 GetPolicyAsync() 所以另一个调用是多余的。

【问题讨论】:

  • 在从 URL/headers 中找出调用者租户后,您可以在中间件中调用 HttpContext 上的 AuthenticateAsync。它允许您指定方案名称。
  • 嗨@christok。如果按照Use multiple authentication schemes在启动时添加授权策略怎么办?是否为每个请求构建了授权策略?

标签: c# asp.net-core jwt azure-ad-b2c


【解决方案1】:

正如@juunas 建议的那样,您可以根据httpcontext 项动态选择要进行身份验证的方案:

app.Use(async (context, next) =>
{
    var host = context.Request.Host.ToString();
    if (true)
    {
        var result = await context.AuthenticateAsync("YourScheme");
        if (!result.Succeeded)
        {
            context.Response.StatusCode = 401;  
            return;
        }

    }
    ....

    await next();
});

您还可以创建自定义身份验证处理程序来读取请求,使用JwtSecurityTokenHandler 验证令牌,最后使用cookie authentication 登录用户。

【讨论】:

  • 感谢您的建议。我确实尝试过这种方法,但它并没有完全实现我所希望的。不过,我更新了这个问题,如果您对此有任何想法,我将不胜感激!
猜你喜欢
  • 2020-10-22
  • 2021-11-27
  • 2020-07-27
  • 2018-02-26
  • 2023-03-10
  • 2017-05-17
  • 2020-09-12
  • 2021-09-17
  • 2018-11-07
相关资源
最近更新 更多