繁体   English   中英

将 ASP.NET 角色授权与 IdentityServer3 隐式流结合使用

[英]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 类类型。

不幸的是,这个映射最终破坏了您定义为namerole的特定声明名称,因为它们的名称被转换并且不再映射到您所期望的。 这会导致[Authorize(Roles = "")]User.IsInRole("")无法按预期工作。

在您的 API Startup.cs您应该添加以下内容:

JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions()
{
    ...
});

编辑:以下信息不正确!。 正如@Paul Taylor 指出的那样,“ AlwaysInclude属性确保相关声明始终存在于身份令牌中(用于客户端,而不是 API。这是一个资源范围,因此该属性无效。”。 感谢您帮助我更多地了解 IdentityServer 的工作原理:-)

对于访问 API 时要包含的 NameRole声明,您需要在 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM