使用带有IdentityServer3隐式流的ASP.NET角色授权

时间:2016-03-07 17:50:06

标签: c# authorization asp.net-core identityserver3

我的单页应用程序使用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属性它始终为null,并且如果我查询User.IsInRole("Administrator")它始终为false,即使将用户分配给该角色也是如此。此外,如果我向Authorize属性([Authorize(Role="Administrator")])添加角色名称,则无论用户是否属于所述角色,都会拒绝用户。

如何使IdentityServer3能够很好地使用ASP.NET角色授权?

1 个答案:

答案 0 :(得分:1)

您是否尝试重置InboundClaimTypeMap

从IdentityServer3文档页面here

  

当您检查关于页面的声明时,您会注意到两个   事情:一些声称有奇怪的长型名称,还有更多的声明   比您在申请中可能需要的那样。

     

长索赔名称来自微软试图映射的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)。这是一个资源范围,因此该属性无效。&#34;。感谢您帮助我更多地了解IdentityServer的工作原理: - )

<击> 对于访问API时要包含的NameRole声明,您需要在alwaysInclude列表中将其标记为ScopeClaim

<击>
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!
        }
    }

<击>