C# 使用具有IdentityServer3隐式流的ASP.NET角色授权
我的单页应用程序使用OidcTokenManager使用隐式流连接到IdentityServer3 STS。客户端将IDS3访问令牌作为承载令牌呈现给ASP.NET核心(WebApi)web服务;web服务应用程序配置为使用IDS3中间件,并使用Authorize属性限制对其方法的访问 SPA客户端配置:C# 使用具有IdentityServer3隐式流的ASP.NET角色授权,c#,authorization,asp.net-core,identityserver3,C#,Authorization,Asp.net Core,Identityserver3,我的单页应用程序使用OidcTokenManager使用隐式流连接到IdentityServer3 STS。客户端将IDS3访问令牌作为承载令牌呈现给ASP.NET核心(WebApi)web服务;web服务应用程序配置为使用IDS3中间件,并使用Authorize属性限制对其方法的访问 SPA客户端配置: new Scope { Name = "BNApi", DisplayName = "BN Api", Enabled = true,
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)
}
}
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Configuration["Authority"],
RequiredScopes = new[] {"BNApi"},
NameClaimType = IdentityModel.JwtClaimTypes.Name,
RoleClaimType = IdentityModel.JwtClaimTypes.Role
});
[Authorize]
public IActionResult Get()
{
...
}
函数配置令牌管理器(){
log(“configureTokenManager()”);
变量配置={
authority:$config.authority,
客户端id:“BNRegistry”,
重定向uri:$config.webRoot+“/#/authorized/”,
post_logout_redirect_uri:$config.webRoot+“/#/”,
响应类型:“id\U令牌”,
范围:“openid配置文件电子邮件BNApi”,
静默重定向uri:$config.webRoot+“/#/renew/”,
沉默的人:是的,
过滤协议声明:错误
};
返回新的管理器(配置);
};
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)
}
}
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Configuration["Authority"],
RequiredScopes = new[] {"BNApi"},
NameClaimType = IdentityModel.JwtClaimTypes.Name,
RoleClaimType = IdentityModel.JwtClaimTypes.Role
});
[Authorize]
public IActionResult Get()
{
...
}
WebApi方法:
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)
}
}
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Configuration["Authority"],
RequiredScopes = new[] {"BNApi"},
NameClaimType = IdentityModel.JwtClaimTypes.Name,
RoleClaimType = IdentityModel.JwtClaimTypes.Role
});
[Authorize]
public IActionResult Get()
{
...
}
这与预期的一样,拒绝使用401密码的未经身份验证的用户。如果我在api控制器方法中检查用户的声明(例如,user.claims.ToList()
),它包含用户已分配到的任何角色的条目
但是,如果检查User.Identity.Name
属性,则该属性始终为空;如果查询User.IsInRole(“管理员”)
则该属性始终为假,即使用户被分配到该角色。此外,如果我在授权属性([Authorize(role=“Administrator”)]
中添加角色名称,则无论用户是否属于所述角色,都将使用401拒绝用户
如何让IdentityServer 3与ASP.NET角色授权配合使用?您是否尝试过重置InboundClaimTypeMap
从IdentityServer3文档页面:
当您检查about页面上的声明时,您会注意到两个
事情:有些声明有奇数长的类型名,还有更多的声明
而不是应用程序中可能需要的
长长的声明名称来自微软的JWT处理程序试图映射
某些声明类型与.NET的ClaimTypes类类型相同
不幸的是,这种映射最终会破坏您定义为name
和role
的特定声明名称,因为它们的名称会被转换,不再映射到您期望的名称。这会导致[Authorize(Roles=“”)]
和用户.IsInRole(“”)
无法按预期工作
在APIStartup.cs
中,应添加以下内容:
JwtSecurityTokenHandler.InboundClaimTypeMap=new Dictionary();
app.useIdentityServerBearTokenauthentication(新的IdentityServerBearTokenauthenticationOptions()
{
...
});
编辑:以下信息不正确!。正如@Paul Taylor所指出的,“AlwaysInclude
属性确保相关声明始终存在于标识令牌中(与客户端而不是API一起使用)。这是一个资源范围,因此属性无效。”。感谢您帮助我进一步了解IdentityServer的工作原理:-)
对于访问API时要包含的名称
和角色
声明,您需要在范围声明
列表中将其明确标记为始终包含
新范围
{
Name=“BNApi”,
DisplayName=“BN Api”,
启用=真,
Type=ScopeType.Resource,
索赔=新名单
{
new ScopeClaim(Constants.ClaimTypes.Name,true),//谢谢@Jamie Dunstan,但是,AlwaysInclude属性确保相关声明始终存在于标识令牌中(用于客户端,而不是API)。这是一个资源范围,因此属性无效。啊,我很抱歉。我的配置是这样的,并假定它是解决方案。您是否尝试重置InboundClaimTypeMap
?即添加JwtSecurityTokenHandler.InboundClaimTypeMap=new Dictionary();
就在app.UseIdentityServerBearerTokenAuthentication(…
在您的APIStartup.cs
?谢谢!这启用了IsInRole(“管理员”)和[Authorize(Roles=“Administrator”)]功能性。User.Identity.Name属性仍然是空的。很遗憾。有什么想法吗?你的应用程序中有这个功能吗?@PaulTaylor-MyUser.Identity.Name
有效是的。我假设你有一个名为“Name”的声明?如果有,你如何添加此声明?@JamieDunstanMar,我没有,这就是问题所在。非常感谢。