HttpClient chamando um método ApiController de autenticação automática do Windows ... mas nenhuma identidade do Windows está chegando

Existe uma maneira do meu controlador de API obter a identidade da conta que iniciou a chamada para o controlador de API quando o controlador de API está usando autenticação do Windows?

Meu "castController.User.Identity" é (do tipo) WindowsIdentity. Mas está "vazio". Vazio, como está: IsAuthenticated = false, e um UserName vazio. Não é nulo, está "vazio".

Meu "WebTier" é um aplicativo IIS em execução com um AppPool personalizado e a IIdentity, que executa o AppPool personalizado, é algo como "mydomain \ myServiceAccount". Estou tentando obter o valor "castController.User.Identity.Name" para ser esta conta de serviço.

(Eu acho que pode ser qualquer cliente que consiga se conectar ao meu WebApiTier com uma conta válida do Windows, mas estou mencionando isso apenas no caso de estar lançando uma chave de macaco estranha)

Meu "WebTier" (aplicativo Mvc) tem este método:

Você notará duas maneiras pelas quais estou usando UseDefaultCredentials. (Aka, eu tenho tentado descobrir isso um pouco)

    private async Task<HttpResponseMessage> ExecuteProxy(string url)
    {
            HttpClientHandler handler = new HttpClientHandler()
            {
                UseDefaultCredentials = true
            };
            handler.PreAuthenticate = true;

            WebRequestHandler webRequestHandler = new WebRequestHandler();
            webRequestHandler.UseDefaultCredentials = true;
            webRequestHandler.AllowPipelining = true;
            webRequestHandler.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired;
            webRequestHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;


            using (var client = new HttpClient(handler)) /* i've tried webRequestHandler too */ 
            {
                Uri destinationUri = new Uri("http://localhost/MyVirtualDirectory/api/mycontroller/mymethod");

                this.Request.RequestUri = destinationUri;

                return await client.SendAsync(this.Request);
            }
    }

Configuração "WebApiTier".

web.config

  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <authentication mode="Windows" />

Código "WebApiTier"

public MyController : ApiController
{

    [ActionName("MyMethod")]
    [MyCustomAuthorization]
    public IEnumerable<string> MyMethod()
    {
                return new string[] { "value1", "value2" };
    }

}


public class MyCustomAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
{

    private string CurrentActionName { get; set; }


    public override void OnAuthorization(HttpActionContext actionContext)
    {
        this.CurrentActionName = actionContext.ActionDescriptor.ActionName;
        base.OnAuthorization(actionContext);
    }

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {

        var test1 = System.Threading.Thread.CurrentPrincipal;
        /* the above is "empty" */

        ////string userName = actionContext.RequestContext.Principal;/*  Web API v2  */
        string userName = string.Empty;
        ApiController castController = actionContext.ControllerContext.Controller as ApiController;
        if (null != castController)
        {
            userName = castController.User.Identity.Name; 
            /* the above is "empty" */
        }

        return true;
    }
}

}

Novamente. Não estou fazendo um "salto duplo" (sobre o qual li em alguns lugares).
As duas camadas estão no mesmo domínio (e desenvolvimento local, na mesma máquina) ....

O engraçado é que eu li isso (Como fazer o HttpClient transmitir credenciais junto com a solicitação? ) e o "problema" relatado é EXATAMENTE como eu quero que o meu funcione. (?!?!).

Para o desenvolvimento, o "WebApiTier" está sendo executado no IIS completo. Para "WebTier", tentei no IIS-Express e no IIS completo.

Também executei um programa de aplicativo de console com este código:

Console App

    IEnumerable<string> returnItems = null;

        HttpClientHandler handler = new HttpClientHandler()
        {
            UseDefaultCredentials = true
        };
        handler.PreAuthenticate = true;


        WebRequestHandler webRequestHandler = new WebRequestHandler();
        webRequestHandler.UseDefaultCredentials = true;
        webRequestHandler.AllowPipelining = true;
        webRequestHandler.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired;
        webRequestHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;


        HttpClient client = new HttpClient(handler);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


    string serviceUrl = "http://localhost/MyVirtualDirectory/api/mycontroller/mymethod";

    HttpResponseMessage response = client.GetAsync(new Uri(serviceUrl)).Result;

    var temp1 = (response.ToString());
    var temp2 = (response.Content.ReadAsStringAsync().Result);

    if (response.IsSuccessStatusCode)
    {
        Task<IEnumerable<string>> wrap = response.Content.ReadAsAsync<IEnumerable<string>>();
        if (null != wrap)
        {
            returnItems = wrap.Result;
        }
        else
        {
            throw new ArgumentNullException("Task<IEnumerable<string>>.Result was null.  This was not expected.");
        }
    }
    else
    {
        throw new HttpRequestException(response.ReasonPhrase + " " + response.RequestMessage);
    }

Mesmo resultado que o outro código. Uma identidade do Windows "vazia".

Eu também passei por isso

http://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication

assim como uma verificação de sanidade.

questionAnswers(1)

yourAnswerToTheQuestion