无法访问身份服务器 4 中的策略(一般情况下的授权)下的安全端点



在我的APIStartup.cs中,我有以下授权策略:

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(...);
...
services.AddAuthorization(options =>
{
options.AddPolicy("VerySecurePolicy", policy =>
{
policy.RequireClaim("admin");
});
options.AddPolicy("VaguelySecurePolicy", policy =>
{
policy.RequireAuthenticatedUser();
});
});
}

然后,我保护两个动作方法,一个具有无参数属性,另一个具有指定的策略。

[Authorize, HttpGet("regular")]
public IActionResult GetRegularData() { return Ok("This is regular level data."); }
[Authorize(Policy = "VerySecurePolicy"), HttpGet("admin")]
public IActionResult GetAdminData() { return Ok("This is admin level data."); }

登录后,我可以访问前者,但不能访问后者。我的推论是,声明admin没有正确地分配给我的用户,我看不到我错过了什么。使用我的访问令牌检查用户信息端点(/connect/userinfo)会给我ID,电子邮件等,但不会给角色admin。检查令牌本身根本没有显示任何声明数组(只有作用域和通常的声明,如subexp等)。

已登录的TestUser实例。

yield return new TestUser
{
SubjectId = "37cfad39-e4da-486b-a8db-a752565125f8", ...
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.Email, "fakey.uno@touchtech.comm"), ...
new Claim(JwtClaimTypes.Role, "admin")
}
};

声明的一个API作用域包含admin作为声明。我已经在访问令牌中验证了这个范围。我还在API资源中添加了这样的信息(尽管我不确定它是否真的需要)。

yield return new ApiScope("test_scope_a1", "Test scope A1", new[] { "admin" });
yield return new ApiResource
{
...
Scopes = new List<string> { "test_scope_a1", ... },
UserClaims = new List<string> { "admin", ... }
};

工作量证明:

  • 类似的设置,但解决方案是不相关的,因为旧版本
  • 不太好回答,不适用于我的情况
  • 似乎确认了我正在做的事情,但缺乏进一步的故障排除

您的VerySecurePolicy策略没有正确设置。像这样定义策略。"claimType"参数为"ClaimTypes.Role",不是"role"[1]。

options.AddPolicy("VerySecurePolicy", policy => {
policy.RequireClaim(claimType: ClaimTypes.Role, "admin"); 
});

或者,如果更合适,可以使用其他require方法。

options.AddPolicy("VerySecurePolicy", policy => {
policy.RequireRole("admin");
});

有相当多这样的方法,它们可以被链接以实现复杂的安全定义。

policy.RequireAuthenticatedUser()
.RequireClaim("client_id", "spa_client")
.RequireRole("admin")
.RequireAssertion(context => context.User.Name == "Konrad");
});

你们在原始样品中实际得到的是admin索赔,而不是role: admin索赔。

同样,您可以访问前一个操作,因为您没有指定策略,并且没有默认/回退策略。这意味着[Authorize]只确保用户被认证。

要使其正常工作,您需要显式地指定它:

[Authorize("VaguelySecurePolicy"), HttpGet("admin")]
public IActionResult GetRegularData() { return Ok("This is regular level data."); }

或者将其设置为回退/默认策略:

services.AddAuthorization(
options => {
options.AddPolicy("VerySecurePolicy", policy => { policy.RequireClaim("role", "admin"); });
// 👇
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
}
);

这确保用[Authorize]注释的操作在没有特定策略集的情况下服从回退策略。


[1]:我们不使用role索赔类型,而是使用其映射的等效http://schemas.microsoft.com/ws/2008/06/identity/claims/role。如果您不希望出现这种映射,并且引用JWT中出现的声明,则需要禁用映射:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(...).AddJwtBearer(...);

现在role索赔将显示为role,sub将显示为sub,如您所料。

注意,这破坏了许多东西,例如,您现在不能使用User.IsInRole("rolename")来检查角色,因为它期望角色声明类型为ClaimTypes.Role。所以我就让它保持原样。

引用

  • https://andrewlock.net/setting-global-authorization-policies-using-the-defaultpolicy-and-the-fallbackpolicy-in-aspnet-core-3/using-the-fallbackpolicy-to-authorize-everything

最新更新