【问题标题】:IdentityServer 4 - Custom IExtensionGrantValidator always return invalid_grantIdentityServer 4 - 自定义 IExtensionGrantValidator 总是返回 invalid_grant
【发布时间】:2019-12-18 10:04:48
【问题描述】:

我的应用要求是使用客户端凭据和另一个代码(哈希)进行身份验证。 我按照这个link 创建和使用自定义IExtensionGrantValidator。 我设法通过批准的授权调用自定义 IExtensionGrantValidator,但客户端总是收到 invalid_grant 错误。

由于某种原因,ResultExtensionGrantValidationContext 的属性)的设置操作总是失败(覆盖 Error 值会将覆盖的值返回给客户端)。

这是CustomGrantValidator代码:

public class CustomGrantValidator : IExtensionGrantValidator
{
    public string GrantType => "grant-name";

    public Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        var hash = context.Request.Raw["hash"]; //extract hash from request
        var result = string.IsNullOrEmpty(hash) ?
            new GrantValidationResult(TokenRequestErrors.InvalidRequest) :
            new GrantValidationResult(hash, GrantType);
        context.Result = result
    }
}

Startup.cs 包含这一行:

services.AddTransient<IExtensionGrantValidator, CustomGrantValidator>();

最后是客户的代码:

        var httpClient = new HttpClient() { BaseAddress = new Uri("http://localhost:5000") };
        var disco = await httpClient.GetDiscoveryDocumentAsync("http://localhost:5000");

        var cReq = await httpClient.RequestTokenAsync(new TokenRequest
        {
            GrantType = "grant-name",
            Address = disco.TokenEndpoint,

            ClientId = clientId,// client Id taken from appsetting.json
            ClientSecret = clientSecret, //client secret taken from appsetting.json
            Parameters = new Dictionary<string, string> { { "hash", hash } }
        });

        if (cReq.IsError)
            //always getting 'invalid_grant' error
            throw InvalidOperationException($"{cReq.Error}: {cReq.ErrorDescription}");

【问题讨论】:

    标签: asp.net-core identityserver4


    【解决方案1】:

    以下代码适用于我的环境:

    public async  Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        var hash = context.Request.Raw["hash"]; //extract hash from request
        var result = string.IsNullOrEmpty(hash) ?
            new GrantValidationResult(TokenRequestErrors.InvalidRequest) :
            new GrantValidationResult(hash, GrantType);
        context.Result = result;
    
        return;
    }
    

    不要忘记注册客户端以允许自定义授权:

    return new List<Client>
        {
            new Client
            {
                ClientId = "client",
    
                // no interactive user, use the clientid/secret for authentication
                AllowedGrantTypes = { "grant-name" },
    
                // secret for authentication
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
    
                // scopes that client has access to
                AllowedScopes = { "api1" }
            }
        };
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,并从@Sarah Lissachell 那里找到了答案,结果我需要实现 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;
          }
      }
      

      然后你必须在你的启动页面中添加这个实现。

      public void ConfigureServices(IServiceCollection services)
      {
      
          // Some other code
          services.AddIdentityServer()
                      .AddDeveloperSigningCredential()
                      .AddAspNetIdentity<Users>()
                      .AddInMemoryApiResources(config.GetApiResources())
                      .AddExtensionGrantValidator<CustomGrantValidator>()
                      .AddProfileService<IdentityProfileService>();
          // More code
      }
      

      【讨论】:

        猜你喜欢
        • 2017-04-24
        • 1970-01-01
        • 1970-01-01
        • 2019-04-09
        • 2021-03-04
        • 1970-01-01
        • 1970-01-01
        • 2021-12-03
        • 2022-01-14
        相关资源
        最近更新 更多