[英]Using ASP.NET Role Authorisation with IdentityServer3 implicit flow
我的单页应用程序使用 OidcTokenManager 使用隐式流连接到 IdentityServer3 STS。 客户端将 IDS3 访问令牌作为承载令牌提供给 ASP.NET Core (WebApi) Web 服务; Web 服务应用程序配置为使用 IDS3 中间件,并使用 Authorize 属性限制对其方法的访问。
SPA客户端配置:
function configureTokenManager() {
console.log("configureTokenManager()");
var config = {
authority: $config.authority,
client_id: "BNRegistry",
redirect_uri: $config.webRoot + "/#/authorised/",
post_logout_redirect_uri: $config.webRoot + "/#/",
response_type: "id_token token",
scope: "openid profile email BNApi",
silent_redirect_uri: $config.webRoot + "/#/renew/",
silent_renew: true,
filter_protocol_claims: false
};
return new OidcTokenManager(config);
};
STS 中的范围配置:
new Scope
{
Name = "BNApi",
DisplayName = "BN Api",
Enabled = true,
Type = ScopeType.Resource,
Claims = new List<ScopeClaim>
{
new ScopeClaim(Constants.ClaimTypes.Name),
new ScopeClaim(Constants.ClaimTypes.Role)
}
}
WebApi 配置:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Configuration["Authority"],
RequiredScopes = new[] {"BNApi"},
NameClaimType = IdentityModel.JwtClaimTypes.Name,
RoleClaimType = IdentityModel.JwtClaimTypes.Role
});
WebApi 方法:
[Authorize]
public IActionResult Get()
{
...
}
这按预期工作,使用 401 拒绝未经身份验证的用户。如果我在 api 控制器方法中检查用户的声明(例如User.Claims.ToList()
),它包含用户拥有的任何角色的条目被分配。
但是,如果我检查User.Identity.Name
属性,它总是为空,如果我查询User.IsInRole("Administrator")
它总是假的,即使用户被分配到该角色。 此外,如果我将角色名称添加到Authorize
属性( [Authorize(Role="Administrator")]
),无论用户是否属于指定的角色,都会以 401 拒绝用户。
如何让 IdentityServer3 与 ASP.NET 角色授权配合得很好?
您是否尝试过重置InboundClaimTypeMap
?
从这里的 IdentityServer3 文档页面:
当您检查关于页面上的声明时,您会注意到两件事:一些声明具有奇怪的长类型名称,并且声明的数量可能超出您的应用程序中所需的数量。
长声明名称来自 Microsoft 的 JWT 处理程序,试图将某些声明类型映射到 .NET 的 ClaimTypes 类类型。
不幸的是,这个映射最终破坏了您定义为name
和role
的特定声明名称,因为它们的名称被转换并且不再映射到您所期望的。 这会导致[Authorize(Roles = "")]
和User.IsInRole("")
无法按预期工作。
在您的 API Startup.cs
您应该添加以下内容:
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions()
{
...
});
编辑:以下信息不正确!。 正如@Paul Taylor 指出的那样,“ AlwaysInclude
属性确保相关声明始终存在于身份令牌中(用于客户端,而不是 API。这是一个资源范围,因此该属性无效。”。 感谢您帮助我更多地了解 IdentityServer 的工作原理:-)
对于访问 API 时要包含的
Name
和
Role
声明,您需要在
ScopeClaim
列表中专门将它们标记为
alwaysInclude
。
new Scope { Name = "BNApi", DisplayName = "BN Api", Enabled = true, Type = ScopeType.Resource, Claims = new List<ScopeClaim> { new ScopeClaim(Constants.ClaimTypes.Name, true), //<-- Add true here new ScopeClaim(Constants.ClaimTypes.Role, true) // and here! } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.