我已经建立了一个既可以充当身份验证/授权服务的API,又可以公开一些用于数据检索的端点。
使用IdentityServer4设置API。我可以通过客户端凭据成功检索访问令牌。但是,当我尝试使用检索到的令牌调用受保护的端点时,我收到未找到的404。日志显示请求未经授权。
我怀疑这与我添加授权策略的方式有关。应该将它全局应用到所有控制器,并使用我在AddAuthentication()
中应用的默认身份验证方案,如下所示:
IdentityModelEventSource.ShowPII = true;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "http://localhost";
options.RequireHttpsMetadata = false;
options.Audience = "identityService";
}).AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}
...
如果删除该策略,我可以呼叫有问题的端点,而不会出现任何问题。
我在做什么错了?
预先感谢
答案 0 :(得分:1)
这里有多个问题。
在客户端凭据流中,没有用户。令牌不包含sub
声明。这就是为什么没有经过身份验证的用户。这说明了未经授权的错误,该错误具有HttpStatusCode 401。
所有方法的过滤器强制authorization 。当未经授权的用户访问某个方法时,这将导致HttpStatusCode404。这意味着某些方法必须对匿名用户保持可用。通过在最低级别上设置AllowAnonymous
属性,可以将方法从全局授权中排除。
例如HomeController:
[AllowAnonymous]
public IActionResult Error()
{
对于客户端凭据流,您可能需要将过滤器更改为令牌一部分,例如范围:
var policy = new AuthorizationPolicyBuilder()
.RequireClaim("scope", "MyScope").Build();
尽管在混合功能(来自IdentityServer和Api)时可能不适合用作全局筛选器。
相反,您可以配置策略和使用属性。在启动时:
Services.AddAuthorization(option =>
{
option.AddPolicy("MyScopePolicy", p => p.RequireScope("MyScope"));
}
在控制器中:
[Authorize("MyScopePolicy")]
[ApiController]
public class MyController : ControllerBase
{