我有受政策保护的 API Controller 。此策略在 Startup.cs 中配置,如
options.AddPolicy("InternalClient", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "client_id" && c.Value == "installation-logic-client-id"))));
而 Controller 方法是:
[HttpGet("{familyId}/versions/{version}/infos")]
[Authorize(Policy = "InternalClient")]
public IActionResult GetTestInfo(Guid testFamilyId, string version)
{
..............................
}
并测试上述方法,我从 MockIdentityServer 获取 token 。在那里我正在配置客户端
yield return new Client
{
ClientId = "installation-logic-client-id",
ClientSecrets = new[] {new Secret("installation-logic-client-secret".Sha256())},
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = new[] {"installation-logic-scope"},
AllowOfflineAccess = true,
AccessTokenType = AccessTokenType.Jwt,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
RefreshTokenExpiration = TokenExpiration.Sliding,
Claims = new List<Claim>() // I want these claims to be added in the access_token so that they can be verified while making the request.
{
new Claim("client_id", "installation-logic-client-id")
},
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true,
};
我总是能成功获得 token ,但不幸的是,该 token 不包含我正在测试和正在为其设置策略的声明信息。 以下是调用..
private async Task<string> GetTokenForInternalClient()
{
var tokenRequest = new ClientCredentialsTokenRequest()
{
Address = await GetTokenEndpoint(),
ClientId = MockConstants.TokenInstallationLogicClientId,
ClientSecret = MockConstants.TokenInstallationLogicClientSecret,
Scope = MockConstants.TokenInstallationLogicScope
};
var tokenResponse = await
_identityServerClient.RequestClientCredentialsTokenAsync(tokenRequest);
if (tokenResponse.IsError) throw new MockIdentityServerException(tokenResponse);
return tokenResponse.AccessToken; // Here I see very short token. Clearly it doesn't contains the claims.
}
目前,我收到“未经授权” 请求。因为由于 claim 不可用,它没有通过政策。 任何人都可以告诉我我做错了什么吗?是否有特定的方法来获取所有声明的 access_token
在 Client 对象内的策略级别将 client_id 更改为 id 之后,还将 TokenType 更改为“Jwt”而不是 opf Reference,我得到了以下 Payload。
{
"nbf": 1574191641,
"exp": 1574195241,
"iss": "http://localhost:5000",
"aud": "installation-logic-scope",
"client_id": "installation-logic-client-id",
"scope": [
"installation-logic-scope"
]
}
更新声明(有效载荷主体)
{
"nbf": 1574198669,
"exp": 1574202269,
"iss": "http://localhost:5000",
"aud": "installation-logic-client-id",
"client_id": "installation-logic-client-id",
"scope": [
"installation-logic-scope"
]
}
Startup.cs
private static void ConfigureAuthorization(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("admin", pb => pb.RequireClaim("Role", "admin", "orgadmin"));
options.AddPolicy("InternalClient", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
((c.Type == "Role" && (c.Value == "admin" || c.Value == "orgadmin")) ||
(c.Type == "id" && c.Value == "installation-logic-client-id")))));
});
}
private void ConfigureDbContexts(IServiceCollection services)
{
........................
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
[UsedImplicitly]
public void Configure(IApplicationBuilder app, PackageHandlingContext dbContext)
{
// middlewares: order is important
app.UseRouting();
app.UseCors("AnyOrigin");
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints => endpoints.MapControllers());
dbContext.Database.EnsureCreated();
}
最佳答案
我想通了整个故事中的所有问题。
首先在memoy ApiResources中构建时,scopes还应该包含“client_id
”。
Scopes = new List<Scope>
{
new Scope(MockConstants.PackageHandlingScope, new[] {"Role", "client_id"})
},
其次,构建测试客户端,只需要使用"id"
作为声明类型,因为client_
已经带有声明类型前缀。
更新后的客户端是
yield return new Client
{
ClientId = MockConstants.TokenInstallationLogicClientId,
ClientSecrets = new[] {new Secret(MockConstants.TokenInstallationLogicClientSecret.Sha256())},
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = new[] {MockConstants.PackageHandlingScope},
AllowOfflineAccess = true,
AccessTokenType = AccessTokenType.Jwt,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
RefreshTokenExpiration = TokenExpiration.Sliding,
Claims = new List<Claim>
{
new Claim("id", "installation-logic-client-id")
}
};
其他都很好。
@Ruard van Elburg 非常感谢您的评论,您指出了构建测试客户端时必需的“id”内容。因为客户声称 alwazs 在通过网络传输到应用程序时会得到前缀。
谢谢
关于c# - 当授予类型为 ClientCredentialsFlow 时,MockIdentityServer 客户端声明不包含在访问 token 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58939442/