我有一个REST API服务,它实现从Azure AD获得的基于JWT bearer token的身份验证 .
// add support for custom Authorization policies
services
.AddAuthorization(authoptions =>
{
authoptions.AddPolicy("MemberOfUsersADGroup", policy =>
policy.Requirements.Add(new IsMemberOfUsersADGroup())
);
})
.AddSingleton<IAuthorizationHandler, IsMemberOfUsersADGroupAuthHandler>();
// add support for this service to recieve OAUTH2 JWT bearer tokens
services
.AddAuthentication(authOptions =>
{
authOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// token validation (REQUIRED)
options.Audience = "AUDIENCE GUID";
options.Authority = String.Format("https://login.microsoftonline.com/[TENANTGUID]/");
});
以下是策略授权处理程序的实现方式 . IT返回 success unconditionally .
public class IsMemberOfSenseiUsersADGroup : IAuthorizationRequirement
{
}
public class IsMemberOfUsersADGroupAuthHandler : AuthorizationHandler<IsMemberOfUsersADGroup>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsMemberOfUsersADGroup requirement)
{
// unconditional success for now
context.Succeed(requirement);
return Task.CompletedTask;
}
}
CASE 1 如果我像这样装饰我的控制器,并且在没有持票人令牌的情况下打电话,那么我会按预期获得401 .
[Authorize]
[Route("api/dostuff")]
public class DoStuffController : Controller
{
CASE 2 但是,如果我使用策略装饰我的控制器,并且在没有持有者令牌的情况下调用, then the REST API call passes fine and doesnt require a bearer token at all!!! 我看到调用进入AuthHandler HandleRequirementAsync()然后它成功,即使承载令牌没有传入 .
[Authorize(Policy = "MemberOfUsersADGroup")]
[Route("api/dostuff")]
public class DoStuffController : Controller
{
我根本无法解释这种行为 . 我很高兴我在测试中发现了这个因为我认为政策检查是附加的(如“AddPolicy”调用所示),但它似乎取代了整个验证链 . 在案例1中由JWT承载中间件完成的那个 .
难道我做错了什么?它是否与在ConfigureServices()中进行的Add ***调用的顺序有关 . 无论策略authhandler检查是否通过,我如何确保JWT不记名承载验证发生?
2 回答
我遇到了同样的问题 . 我的解决方法是将控制器置于默认的
[Authorize]
属性下,然后每个操作都有自己的策略[Authorize(Policy = "MemberOfUsersADGroup")]
. 对我而言,'t such a big deal because I had only one controller which action'是根据同样的政策 . RequireAuthenticatedUser和类似的没有必要 .这是预期的行为 .
如果您希望授权策略拒绝未经身份验证的请求,只需调用builder.RequireAuthenticatedUser()即可 .