Accessing ServiceSecurityContext.Current.PrimaryIdentity.Name from within a WCF service - wcf

I'm very new to WCF, but I've searched this topic pretty thoroughly and haven't come up with a satisfactory answer, so here goes my question:
While within my WCF service, I need to access the user's username. From everything I've read, I should be able to get that from ServiceSecurityContext.Current.PrimaryIdentity.Name. However, instead of returning Domain\Username as I had hoped, it always returns NT AUTHORITY\NETWORK SERVICE . How can I get the actual Domain and Username of the individual that is logged in to the machine accessing my service?
Thanks.

Have you looked at the ServiceSecurityContext Class?
Represents the security context of a remote party. On the client,
represents the service identity and, on the service, represents the
client identity.
e.g.
ServiceSecurityContext.Current.WindowsIdentity.Name
...ensuring that you have your service set up to authenticate via Windows security.

To Use Windows credentials , set the clientCredentialType to "Windows". use wsHttpBinding, or netTcpBinding if its within LAN
<bindings>
<netTcpBinding>
<binding name="WindowsCredentials">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>

Related

Basicbinding ServiceSecurityContext Null

I have a service that uses wsHttpBinding security mode="Message" message clientCredentialType="Windows" negotiateServiceCredential="false" establishSecurityContext="false" .
When a client calls the service, on the service side I can use ServiceSecurityContext context = OperationContext.Current.ServiceSecurityContext; in order to get the callers credentials.
However, now I need a Java client to call this service. Apparently, wsHttpBinding does not interop easily w/Java (I thought that was the whole point of services). So I need to change the binding to basicHttpBinding to get the interop, but now OperationContext.Current.ServiceSecurityContext returns null.
I have tried mutliple combinations from posts I have seen, but all the post are slightly different and did not work for me.
I am hoping that someone smarter than I can resolve this once and for all.
Here are the requirements:
1.)Basicbinding needs to be used.
2.)OperationContext.Current.ServiceSecurityContext needs to be populated automatically and retrieved on server side like it is with wsHttpBinding.
Here are the basic bindings I used among others..
<basicHttpBinding>
<binding name="CustomBasicBinding"
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
Is it possible?
Thanks in advance

What is the equivalent of passing DefaultCredentials in WCF?

This answer explains that when calling a .asmx web service there's no need to specify which authentication type to use:
WebServiceProxy proxy = new WebServiceProxy(); // Derived from SoapHttpClientProtocol
proxy.Credentials = CredentialCache.DefaultCredentials;
This method works for both NTLM and Kerberos authentication. It will pass the credentials of the windows account under which the code is running.
What is the equivalent in WCF, that works in both NTLM and Kerberos environments?
In WCF you need to specify authentication in the bindings of your WCF services. Make sure the client and server use the same authentication scheme.
web.config:
<binding name="WindowsClientOverTcp">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>

WCF call with windows authentication

We have a system where the users access a web server, the web server then calls a WCF service.
We would like the call to the WCF service to be made in the security context of the windows identity of the application pool on the web server.
What is the best way to do this? Can it be done purely through configuration in the web.config file.
Thanks
Shiraz
Yes, you should be able to do this, all in config:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="WinAuth" mode="Transport">
<transport clientCredentialType="Windows" />
<bindings>
</netTcpBinding>
</bindings>
</system.serviceModel>
Of course, depending on your binding, you'd have to use a different tag under the <bindings> parent node - and of course, not all bindings support all security modes.....
In your endpoint, use the appropriate binding and then just reference this config:
<endpoint name="WCFService" address="......."
binding="netTcpBinding"
bindingConfiguration="WinAuth"
contract="......" />
That should do it! And of course, if you need message security instead of transport security, you can do that, too.
In your WCF service method, you can check to see whether or not the Windows credentials have been sent over, and what they are, by checking:
ServiceSecurityContext.Current.WindowsIdentity
This will be NULL if you don't have a Windows caller, otherwise it will show who called you.
Marc

WCF/basicHttp and NTLM authentication

Does anyone know how exactly NTLM authentication works in WCF/basicHttp? I wonder if user credentials are passed for every single service method call, or if some kind of security token is being used for subsequent service method calls.
The exact binding configuration that I am using:
<bindings>
<basicHttpBinding>
<binding name="winAuthBasicHttpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>
</bindings>
I found this type of configuration on the MSDN reference. But I am not sure if this a good idea performance wise. An alternative would be providing a custom GetAuthenticationToken() kind of method to provide a security token for all subsequent requests of the client. This could be done via the Enterprise Library - Security Application Block.
Further details: The service is being consumed by Browsers/Silverlight Clients.
In this case here, every single method call will be authenticated.
What you're talking about would be what is called "secure sessions", where the client authenticates once against the server and then a common token is used for subsequent exchanges. That secure sessions features however is only available with wsHttpBinding - not with basicHttpBinding.
Marc

WCF - Preventing Unauthorized Clients

I have a WCF service that I only want my applications to have access to. My applications consist of a traditional web interface that uses JQuery and a Silverlight interface. Neither of these interfaces require the user to login.
Is there a way that I can tell a WCF service to only allow clients that originated from my domain? If so, how?
Thank you!
Yes, of course you can - just require Windows credentials (i.e. an Active Directory account in your domain) from your callers.
Anyone not authenticated against your domain will be rejected.
You can do this by specifying either netTcpBinding with transport security (if everything is behind a corporate firewall), or wsHttpBinding with message security:
<bindings>
<netTcpBinding>
<binding name="DomainUsersOnly">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
<wsHttpBinding>
<binding name="HttpDomainUsersOnly">
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
Now, all you need to do is reference one of those binding configurations in your endpoints:
<endpoint name="whatever"
address="......"
binding="netTcpBinding"
bindingConfiguration="DomainUsersOnly"
contract="IYourservice" />
and you should be good to go.
If all of your legitimate users are supposed to be on your internal corporate LAN (on the same subnet), then you could lock it down by IP address using an approach like this. You could also clamp it down to several specific IP masks that way if you wanted to.
But if you want to allow legitimate users to hit it from anywhere, then this is not a good approach. Authentication would be better in that case.
You could add a security restriction in IIS to only allow calls from the domain to the webservice.
Unless you consider windows auth (since requests are coming from your domain), the preferred way to do this would be at a different level, via firewalls. At that level, you can restrict incoming traffic to a known set of IP addresses. This will only go so far, since IPs can be spoofed, but this is an open service, so there you go. A better alternative would be both firewalls and windows auth.
Alternatively, you could check client IP addresses in WCF by querying OperationContext.Current.IncomingMessageProperties.