IdentityServer4:如何仅返回当前范围的声明

IdentityServer4:如何仅返回当前范围的声明,identityserver4,Identityserver4,我有一个客户端,它可以从2个不同的资源访问2个作用域。每个范围都有自己的声明。但是,我注意到,来自两个作用域的所有声明都将返回给每个资源。如何确保只将与正确范围相关的声明返回到资源 以下是我在启动时的资源: //I use IdentityServer3.AccessTokenRequest since my resource is a .net app public void Configuration(IAppBuilder app) { app.UseIdentityServer

我有一个客户端,它可以从2个不同的资源访问2个作用域。每个范围都有自己的声明。但是,我注意到,来自两个作用域的所有声明都将返回给每个资源。如何确保只将与正确范围相关的声明返回到资源

以下是我在启动时的资源:

//I use IdentityServer3.AccessTokenRequest since my resource is a .net app

public void Configuration(IAppBuilder app)
{
    app.UseIdentityServerBearerTokenAuthentication(new identityServerBearerTokenAuthenticationOptions
    {
        Authority = URLToIdentityServer,
        RequiredScopes = new[] { "SomeAPI.read" } //Notice this is scope we want claims for.
    });  

    //Some other stuff
}
以下是我在identity server中的功能:

public static IEnumerable<Client> GetClients()
{
        return new List<Client>
        {
            new Client
            {
                ClientId = "ClientId",
                ClientName = "Client Name",
                ClientSecrets = new List<Secret> {new Secret("SuperSecret".Sha256())}, 
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                AllowedScopes = new List<string> {"SomeAPI.read", "OtherAPI.write"},  //Notice client has access to 2 scopes from 2 resources.
                Claims = claims
            }
        };
}

private static ICollection<Claim> claims = new List<Claim>
{
        new Claim("Claim1", "Value1"), //Belongs to scope "SomeAPI.read"
        new Claim("Claim2", "Value2"), //Belongs to scope "SomeAPI.read"
        new Claim("Claim3", "Value3"), //Belongs to scope "OtherAPI.write"
        new Claim("Claim4", "Value4"), //Belongs to scope "OtherAPI.write"
};
public静态IEnumerable GetClients()
{
返回新列表
{
新客户
{
ClientId=“ClientId”,
ClientName=“客户端名称”,
ClientSecrets=new List{new Secret(“SuperSecret”.Sha256())},
AllowedGrantTypes=GrantTypes.ClientCredentials,
AllowedScopes=new List{“SomeAPI.read”,“OtherAPI.write”},注意,客户端可以从2个资源访问2个作用域。
索赔=索赔
}
};
}
私有静态ICollection声明=新列表
{
新声明(“Claim1”、“Value1”),//属于范围“SomeAPI.read”
新声明(“Claim2”、“Value2”),//属于范围“SomeAPI.read”
新声明(“Claim3”、“Value3”),//属于范围“OtherAPI.write”
新声明(“Claim4”、“Value4”),//属于范围“OtherAPI.write”
};
万一您想知道资源和作用域是如何声明的:

public static IEnumerable<ApiResource> GetApiResources()
{
        return new List<ApiResource>
        {
            new ApiResource
            {
                Name = "SomeAPI",
                DisplayName = "Some API",
                Description = "This is the resource which we expect 2 claims for, but get 4",
                ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
                Scopes = new List<Scope>
                {
                    new Scope("SomeAPI.read", readClaimTypes),
                },
                Enabled = true,
            },

            new ApiResource
            {
                Name = "OtherAPI",
                DisplayName = "Other API",
                Description = "Another API that also has a scope with 2 claims and we don't want to get these claims back in the resource they don't belong to",
                ApiSecrets = new List<Secret> {new Secret("SomeOtherSecret".Sha256())},
                Scopes = new List<Scope>
                {
                        new Scope("OtherAPI.write", writeClaimTypes)
                },
                Enabled = true,
            }
        };
}

private static IEnumerable<string> readClaimTypes = new List<string> {"claim1", "claim2"};
private static IEnumerable<string> writeClaimTypes = new List<string> {"claim3", "claim4"}; 
}
public静态IEnumerable GetApiResources()
{
返回新列表
{
新资源
{
Name=“SomeAPI”,
DisplayName=“一些API”,
Description=“这是我们期望得到2个索赔,但得到4个索赔的资源”,
ApiSecrets=new List{new Secret(“ScopeSecret”.Sha256())},
范围=新列表
{
新范围(“SomeAPI.read”,readClaimTypes),
},
启用=真,
},
新资源
{
Name=“OtherAPI”,
DisplayName=“其他API”,
Description=“另一个API也有一个包含2个声明的作用域,我们不想让这些声明回到它们不属于的资源中”,
ApiSecrets=new List{new Secret(“SomeOtherSecret”.Sha256())},
范围=新列表
{
新范围(“OtherAPI.write”,writeClaimTypes)
},
启用=真,
}
};
}
私有静态IEnumerable readClaimTypes=新列表{“claim1”、“claim2”};
私有静态IEnumerable writeClaimTypes=新列表{“claim3”,“claim4”};
}

通过这种配置,我希望我的资源只获得前两个声明。但这都是4。任何帮助都将不胜感激。

这种行为似乎是有意为之。如果您查看以下内容:

声明:允许设置客户端的声明(将包含在 访问令牌)

我试图改变配置,但没有解决它。我还使用ProfileService尝试了以下操作。但这不是办法


改变行为的唯一方法是在那里添加一个过滤器,而不改变集合。

当您说资源正在获取所有索赔时。您的意思是,当您访问一个API调用时,每个API都会看到所有声明吗?正确。当我检查受保护资源/web api(在本例中为“SomeAPI”)中的用户(Prinicipal)声明时,我看到所有4个声明都存在。我曾假设,当api调用identity service来验证客户端的访问令牌时,返回的声明将被它们所属的范围过滤。Os这真的是一个问题吗?看所有的用户声明?不,这对我个人来说不是一个问题,尽管从长远来看它代表了潜在的规模问题(如果您的id服务器被许多资源使用,这对我们来说是不现实的)。我主要是想证明这样做可以避免对我们的身份验证过程进行彻底的修改。我还意识到我在这里混淆了授权和身份验证之间的界限。用户声明只包括客户端请求访问的资源的声明。请确保您没有在e access token。这样,它们只存在于id token中。谢谢。最后,我决定做正确的事情,让identity server只担心身份验证。每个受保护的应用程序/资源都将对DB进行单独的ping,以根据用户客户端id获取相关声明。这是正确的做法,但我想看看我是否参与其中我会很懒,在一次电话里做到这两件事。
public class ProfileService : IProfileService
{
    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        // DO NOT USE!!!
        if (context.Caller == "ClaimsProviderAccessToken")
        {
            var claims = context.Client.Claims
                         .Where(c => context.RequestedClaimTypes.Contains(c.Type)).ToList();

            // Replace the list. This overwrites the in memory collection!
            // This will eventually result in an empty list for all tokens.
            // The collection may not be altered!
            context.Client.Claims = claims;
        }
    }
}