使用扩展授权的Identity Server 4 Windows身份验证不起作用

时间:2019-08-16 00:03:39

标签: identityserver4

我已经为客户端凭据和隐式流设置了身份服务器4,并且都工作正常。现在,我编写了扩展许可以支持Windows身份验证,但是它始终在ValidateAsync方法中从AuthenticateAsync返回false。

我的问题与这篇帖子IdentityServer4 Resource owner password and Win auth: unauthorized

中提到的问题相同

但没有人回答该帖子

public class WinAuthGrantValidator : IExtensionGrantValidator
    {
        private readonly HttpContext _httpContext;
        private readonly IClientSecretValidator _clientValidator;

        public string GrantType => "CustomWindowsAuth";

        public WinAuthGrantValidator(IClientSecretValidator clientValidator,IHttpContextAccessor httpContextAccessor)
        {
            _httpContext = httpContextAccessor.HttpContext;
            _clientValidator = clientValidator;
        }

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            // validate client
            var clientResult = await _clientValidator.ValidateAsync(_httpContext);
            if (clientResult.Client == null)
            {
               // _httpContext.Response.StatusCode = 401;
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient);
                return;
            }

            var result = await _httpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
            if (result?.Principal is WindowsPrincipal wp)
            {
                var roles = wp.Claims.ToList();

                var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
                id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
                id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));
                if (AccountOptions.IncludeWindowsGroups)
                {
                    var wi = wp.Identity as WindowsIdentity;
                    var groups = wi?.Groups?.Translate(typeof(NTAccount),false);
                    if (groups != null)
                    {
                        roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value)).ToList();
                        id.AddClaims(roles);
                    }
                }
                context.Result = new GrantValidationResult(wp.Identity.Name, GrantType, roles);

            }
            else
            {

                await _httpContext.ChallengeAsync(AccountOptions.WindowsAuthenticationSchemeName);
                context.Result = new GrantValidationResult(TokenRequestErrors.UnauthorizedClient, "Invalid credential");
            }
        }
    }

这是上面的身份服务器注册

services.Configure<IISOptions>(iis =>
            {
                iis.AuthenticationDisplayName = "Windows";
                iis.AutomaticAuthentication = false;
            });

  var builder = services.AddIdentityServer(options =>
                {

                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                })
                .AddSigningCredential(Certificate.Certificate.LoadCertificateFromStore(thumbPrint, logger))
                .AddAspNetIdentity<TUserIdentity>()
                .AddIdentityServerStoresWithDbContexts<TConfigurationDbContext, TPersistedGrantDbContext>(configuration)
                 .AddExtensionGrantValidator<WinAuthGrantValidator>()
                .AddProfileService<CustomProfileService>();

这是来自客户端的代码

var client = new HttpClient(new HttpClientHandler
    {
        UseDefaultCredentials = true
    });

    var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
    {
        Address = "http://marsdevhv020.identity.marsdev.co.nz",
        Policy =
        {
            RequireHttps = false
        }
    });

    var tokenResponse = await client.RequestTokenAsync(new TokenRequest
    {
        Address = disco.TokenEndpoint,
        GrantType = "CustomWindowsAuth",
        ClientId = "WindowsClient",
        ClientSecret = "WindowsClientSecret",
        Parameters =
        {
            { "scope", "TestApi.Read" }
        }
    });


    if (tokenResponse.IsError)
    {
        Console.WriteLine(tokenResponse.Error);
        Console.WriteLine("Press any key to exit!");
        Console.Read();
    }

    Console.WriteLine(tokenResponse.AccessToken);

它总是返回错误并总是返回结果吗?主体为空

1 个答案:

答案 0 :(得分:0)

ChallengeAsync 在自定义授权验证器中使用时似乎无法正常工作。您可以使用自定义中间件来解决它:

        public async Task Invoke(HttpContext httpContext)
        {
            if (!httpContext.User.Identity.IsAuthenticated)
            {
                await httpContext.ChallengeAsync("Windows");
            }
            else
            {
                 await _next(httpContext);
            }
        }

这将在到达您的验证器之前强制进行身份验证,现在应该设置原则。