[英].NET Core does not show user claims in middleware when authenticating with Azure AD
我有一个多租户.NET Core Web应用程序,其中当前用户的租户通过中间件解决。 特别是,租户通过名为SaasKit.Multitenancy的库解决。
要使用此库,请将此行放在ConfigureServices()
:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// (omitted for brevity)
// The 'Tenant' type is what you resolve to, using 'ApplicationTenantResolver'
services.AddMultitenancy<Tenant, ApplicationTenantResolver>();
// ...
}
然后将这一行放入Configure()
以将其添加到中间件管道中:
public void Configure(IApplicationBuilder app)
{
// ...
app.UseAuthentication();
app.UseMultitenancy<Tenant>(); //this line
app.UseMvc(ConfigureRoutes);
// ...
}
这将导致在中间件中执行以下方法,从而解决当前用户的租户:
public async Task<TenantContext<Tenant>> ResolveAsync(HttpContext context)
{
//whatever you need to do to figure out the tenant goes here.
}
这允许将此方法的结果(无论解决租户的情况如何)注入到所需的任何类中,如下所示:
private readonly Tenant _tenant;
public HomeController(Tenant tenant)
{
_tenant = tenant;
}
到目前为止,我们一直在使用.NET Identity平台对用户进行身份验证,并将用户数据存储在应用程序的数据库中。 但是,我们的新租户希望能够通过SSO对用户进行身份验证。
我已经弄清了大多数SSO内容-我正在使用Azure AD登录用户,并且我组织的Azure AD租户将能够与其身份提供商进行联盟 。 简而言之, ConfigureServices
以下代码添加了Identity和AzureAD身份验证:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// rest of the code is omitted for brevity
services.AddIdentity<ApplicationUser, ApplicationRole>(config =>
{
config.User.RequireUniqueEmail = true;
config.Password.RequiredLength = 12;
}).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => _configuration.Bind("AzureAd", options)).AddCookie();
// policy gets user past [Authorize] if they are signed in with Identity OR Azure AD
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder(
AzureADDefaults.AuthenticationScheme,
IdentityConstants.ApplicationScheme
).RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
}
使用身份时,我已经能够使用UserManager解决用户的租户,如下所示:
public async Task<TenantContext<Tenant>> ResolveAsync(HttpContext context)
{
TenantContext<Tenant> tenantContext = new TenantContext<Tenant>(new ApplicationTenant());
if (context.User.Identity.IsAuthenticated)
{
var user = await _userManager.Users
.Include(x => x.Tenant)
.FirstOrDefaultAsync(x => x.UserName == email);
if (user?.Tenant != null)
{
tenantContext = new TenantContext<Tenant>(user.Tenant);
_logger.LogDebug("The current tenant is " + user.Tenant.Name);
return await Task.FromResult(tenantContext);
}
}
return await Task.FromResult(tenantContext);
}
我的计划是修改此代码,以便抓住当前用户的声明,该声明可用于推断用户属于哪个租户。 但是,通过Azure AD对用户进行身份验证时,尽管已登录用户,但中间件中的HttpContext.User
始终为空。它不是null,但HttpContext.User.Identity.IsAuthenticated
始终为false,而HttpContext.User.Claims
为空。 我只看到HttpContext.User
的值,一旦路由完成并且代码到达Controller后,就会填充该用户。
我试图以几乎所有可行的方式来重组中间件,但无济于事。 让我感到困惑的是,当用Identity验证用户时,在租户解析器中填充了HttpContext.User
。 考虑到这一点,我不确定在通过Azure AD进行身份验证时如何在中间件中访问用户的声明。
我能想到的最好的解决方案是,修改对当前租户注入到代码中的每个实例的调用,该方法调用一种通过索偿解决租户的方法。 如果租户在受[Authorize]属性限制的区域中为null,则意味着该用户通过Azure AD登录,这使我可以查看他们的声明。 但是,我无法在中间件中访问用户的声明确实让我感到困扰,因为我不确定这里到底发生了什么。
由于您尝试从自定义组件访问HttpContext,因此需要将HttpContextAccessor
添加到服务集合中,如下所示:
services.AddHttpContextAccessor();
现在,您可以使用依赖项注入根据需要解析HttpContext
。 根据您对中间件的控制程度,这可能有用也可能没有帮助。
对于它的价值,仅使用MSAL而无需其他第三方中间件就可以对AAD进行身份验证几乎没有问题。 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.