IdentityServer4 IExtensionGrantValidator

IdentityServer4 IExtensionGrantValidator,identityserver4,Identityserver4,我有一个基本的IdentityServer4令牌服务器、一个Api和一个基于IdentityServer4文档教程的使用客户端凭据的测试客户端应用程序设置 我们有一个预构建的客户端应用程序,用户可以使用其现有凭据登录,该凭据不绑定到IdentityServer4。客户端应用程序将使用客户端凭据工作流调用Api,因为我不想为可能需要访问Api的每个客户端应用程序创建多个用户 使用上面的IdentityServer4设置,我可以正确地使用客户端凭据工作流。我面临的问题是,虽然我不需要单个用户对自己进

我有一个基本的IdentityServer4令牌服务器、一个Api和一个基于IdentityServer4文档教程的使用客户端凭据的测试客户端应用程序设置

我们有一个预构建的客户端应用程序,用户可以使用其现有凭据登录,该凭据不绑定到IdentityServer4。客户端应用程序将使用客户端凭据工作流调用Api,因为我不想为可能需要访问Api的每个客户端应用程序创建多个用户

使用上面的IdentityServer4设置,我可以正确地使用客户端凭据工作流。我面临的问题是,虽然我不需要单个用户对自己进行身份验证,但我仍然希望通过用户id知道他们是谁。我可以简单地将&user\u id=9999添加到令牌请求中,但在发出请求时,我找不到从令牌服务器检索此信息的方法。经过一些研究,我发现了IExtensionGrantValidator,它允许我添加cstom授权类型,拦截请求并进行一些自定义处理。问题是,即使看起来我设置正确,我仍然会收到无效的\u grant错误

代码如下:

public class CustomGrantValidator : IExtensionGrantValidator
{
    public string GrantType => "custom_credentials";

    public Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        return Task.FromResult(context.Result);
    }
}
在新客户端块中:

 AllowedGrantTypes =
 {
     GrantType.ClientCredentials,
     "custom_credentials"
 },
启动中

.AddExtensionGrantValidator<CustomGrantValidator>();
.AddExtensionGrantValidator();

我不熟悉IdentityServer4和.net Core,因此我确信我做错了什么,或者不理解这里的基本机制。

我发现这一点是因为我遇到了相同错误的问题,但我确信您的验证器是无用的,因为它什么都不做。您需要在上下文中设置结果,如下所示:

        var claims = new List<Claim>();

        claims.Add(new Claim("sub", userToken));
        claims.Add(new Claim("role", "admin"));

        context.Result = new GrantValidationResult(userToken, "delegation", claims: claims);
var索赔=新列表();
添加(新的索赔(“sub”,userToken));
添加(新的声明(“角色”、“管理员”);
context.Result=新的GrantValidationResult(userToken,“委托”,声明:声明);

我看到的每个示例都通过添加此值来设置结果。

为了获得具有成功答案的IExtensionGrantValidator,您必须实现接口IProfileService。此接口有一个名为IsActiveAsync的方法。如果不实现此方法,ValidateAsync的答案将始终为false。在这里,我将向您展示一个实现示例:

public class IdentityProfileService : IProfileService
    {

        //This method comes second
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            //IsActiveAsync turns out to be true 
            //Here you add the claims that you want in the access token
            var claims = new List<Claim>();

            claims.Add(new Claim("ThisIsNotAGoodClaim", "MyCrapClaim"));

            context.IssuedClaims = claims;
        }

        //This method comes first
        public async Task IsActiveAsync(IsActiveContext context)
        {           
            bool isActive = false;
            /*
                Implement some code to determine that the user is actually active 
                and set isActive to true
            */
            context.IsActive = isActive;
        }
    }
公共类标识profileservice:IProfileService
{
//这种方法排在第二位
公共异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
//事实证明,IsActiveAsync是正确的
//在这里,您可以在访问令牌中添加所需的声明
var索赔=新列表();
添加(新索赔(“ThisisNotGoodClaim”、“MyCrapClaim”);
context.IssuedClaims=索赔;
}
//这种方法是第一位的
公共异步任务IsActiveAsync(IsActiveContext上下文)
{           
bool isActive=false;
/*
实现一些代码以确定用户是否实际处于活动状态
并将isActive设置为true
*/
context.IsActive=IsActive;
}
}
然后,您必须在启动页面中添加此实现

public void ConfigureServices(IServiceCollection services)
{

    // Some other code
services.AddIdentityServer()
                    .AddDeveloperSigningCredential()
                    .AddAspNetIdentity<Users>()
                    .AddInMemoryApiResources(config.GetApiResources())
                    .AddExtensionGrantValidator<CustomGrantValidator>()
                    .AddProfileService<IdentityProfileService>();
    // More code
}
public void配置服务(IServiceCollection服务)
{
//其他代码
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddAsNetIdentity()
.AddInMemoryApiResources(config.GetApiResources())
.AddExtensionGrantValidator()
.AddProfileService();
//更多代码
}

您的实现可能(我认为这将)更加复杂,但我希望这为您提供了一个良好的起点。

您是如何解决的?我相信我找到了一种添加声明的方法,而无需通过GrantValidator,但我不再拥有代码,也记不起我最终做了什么。最终,我放弃了IdentityServer 4。由于跨框架的兼容性问题,无论怎样,对于我试图实现的目标来说,这都是过分的。我决定使用一个.NETJWT实现,它对我们的用例更有意义。