我正在开发一个使用 Microsoft Entra ID 进行身份验证的 ASP.NET Core MVC 应用程序。该应用程序设计为多租户,我想限制仅特定租户的用户访问。我的
AllowedTenants
文件中有一个 appsettings.json
数组,我试图拒绝此数组中未指定的租户的用户访问。但是,我当前的实现并未按预期工作,未经授权的租户的用户仍然可以访问该应用程序。
相关代码片段来自
Program.cs
var allowedTenants = builder.Configuration.GetSection("AzureAd:AllowedTenants").Get<string[]>();
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph:Scopes").Get<string[]>())
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph"))
.AddInMemoryTokenCaches();
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
var existingOnTokenValidatedHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await existingOnTokenValidatedHandler(context);
var tenantId = context.Principal?.FindFirst("tid")?.Value;
if (!allowedTenants!.Contains(tenantId))
{
throw new UnauthorizedAccessException("This tenant is not authorized");
}
};
});
相关代码片段来自
appsettings.json
"AzureAd": {
"Instance": "microsoft_instance",
"Domain": "my_domain",
"ClientId": "my_client_id",
"ClientSecret": "my_client_secret",
"TenantId": "organizations",
"CallbackPath": "/signin-oidc",
"AllowedTenants": [ "tenant_a", "tenant_b" ]
},
"DownstreamApis": {
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": [ "User.Read", "User.ReadWrite.All" ]
}
},
我希望应用程序抛出 UnauthorizedAccessException 并拒绝来自未在 AllowedTenants 数组中列出的租户的用户的访问。但是,未经授权的租户的用户仍然可以访问该应用程序。
您正在使用不同的
AthenticationScheme
来注册 Authentication 和 JwtBearerOptions。所以我认为这些方法之一应该可以解决这个问题:
1- 使用相同的 AthenticationScheme 名称
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
...
builder.Services.Configure<JwtBearerOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
...
2- 使用
AddJwtBearer
扩展方法合并 JwtBearerOptions
首先,你需要有
Microsoft.AspNetCore.Authentication.JwtBearer
:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Events.OnTokenValidated = async context =>
{
var tenantId = context.Principal?.FindFirst("tid")?.Value;
if (!allowedTenants!.Contains(tenantId))
{
throw new UnauthorizedAccessException("This tenant is not authorized");
}
};
});
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph:Scopes").Get<string[]>())
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph"))
.AddInMemoryTokenCaches();