I have the following situation:
WPF client application -> WCF Service -> WebApi Service
I want to be able to authenticate the user of the client application when in the WebApi service. I do not require full impersonation/delegation - all I require is the client's login ID, as I am using the user ID for a third party authorisation system. Both WCF Service and Web Api Service are on the same server.
The current approach I am trying is Impersonation of the WindowsIdentity, as follows.
1. WebApi service self-hosted with Owin
WebApp.Start(options,
builder =>
{
// Authenticate POST requests, but not GET requests
// Adapted from: http://stackoverflow.com/questions/17457382/windows-authentication-with-signalr-and-owin-self-hosting
var listener = (HttpListener)builder.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemes =
AuthenticationSchemes.Negotiate | AuthenticationSchemes.Anonymous;
listener.AuthenticationSchemeSelectorDelegate =
request => (request.HttpMethod == HttpMethod.Get.Method)
? AuthenticationSchemes.Anonymous
: AuthenticationSchemes.Negotiate;
// etc
});
2. WCF Service
In <system.web>
: <authentication mode="Windows" />
In <bindings>
:
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
In the code for the specific function I want to impersonate:
WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (callerIdentity.Impersonate())
{
var request = ...;
request.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
request.UseDefaultCredentials = true;
// Use request to call Web Api
}
3. In the client:
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
With this set-up, all on my local PC, I see an error from the WCF service trying to connect to the WebApi service:
{"An attempt was made to access a socket in a way forbidden by its access permissions 127.0.0.1:9102"}
(Note that using WindowsIdentity callerIdentity = WindowsIdentity.GetCurrent();
instead of WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
works fine - although obviously this is using the WCF user rather than then client app user)
My question - is this the most sensible way of determining the user name in the Web Api service? Is it even possible like this? If so, any idea how to debug the "forbidden" error and get this set-up working?