Short Version: Why when I impersonate a web-request made by Windows Store app, I get WindowsIdentity object with correct user name, but its IsAuthenticated property returns False? Making same request from a browser (including Metro IE10) gives IsAuthenticated==true.
Long Version:
I'm prototyping an internal enterprise solution, which consists of WCF-service and WinJS application. WCF-service is based on the webHttpBinding (i.e. simple GET/POST requests).
Certain actions need to be processed on behalf of a user making request, therefore service is configured to impersonate its callers. Here is sample configuration:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="CustomizedWebBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="Web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WcfService">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="CustomizedWebBinding" contract="IWcfService" behaviorConfiguration="Web">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8787/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
... and code:
public class WcfService : IWcfService
{
[OperationBehavior(Impersonation=ImpersonationOption.Required)]
public UserInfo GetUserInfo()
{
UserInfo ui = new UserInfo();
WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;
ui.UserName = identity.Name;
ui.IsAuthenticated = identity.IsAuthenticated;
ui.ImpersonationLevel = identity.ImpersonationLevel.ToString();
ui.IsAnonymous = identity.IsAnonymous;
ui.IsGuest = identity.IsGuest;
ui.IsSystem = identity.IsSystem;
ui.AuthenticationType = identity.AuthenticationType;
return ui;
}
}
So, this operation simply collects information about the caller and sends it back in a json string.
Moving to the client. To enable automatic authentication I checked "Enterprise Authentication", "Internet (Client)" and "Private Networks" in the Windows Store app's manifest file.
From within Windows Store app, I send request using WinJS.xhr function:
var options = {
url: "http://localhost:8787/getuserinfo"
};
WinJS.xhr(options).then(function (xhrResponse) {
var userInfoBlock = document.getElementById("userInfoBlock");
var data = JSON.parse(xhrResponse.response);
userInfoBlock.innerHTML += "<ul>"
for (var p in data) {
if (data.hasOwnProperty(p)) {
userInfoBlock.innerHTML += "<li>" + p + ": " + data[p] + "</li>";
}
}
userInfoBlock.innerHTML += "</ul>";
});
Now, when I execute Windows Store app and it sends request, the response I get is:
AuthenticationType: "NTLM"
ImpersonationLevel: "Impersonation"
IsAnonymous: false
IsAuthenticated: false
IsGuest: false
IsSystem: false
UserName: "TESTBOX\dev"
If I send request using browser's address bar, I get same response, with the only difference that "IsAuthenticated: true".
I also noticed that if I disable "Enterprise Authentication", it causes Credentials Picker to popup and after providing correct credentials I'm getting "IsAuthenticated: true".
Am I missing something or expecting too much from the enterpriseAuthentication capability?
I think I've stumbled across the same (Calling a WCF service using Windows Auth from a Windows Store App) and it looks like Windows Store Apps with enterprise authentication prevent calls to services on localhost using impersonation.
When I hosted my service on another server on the domain it worked just fine.