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
Related
I'm having some issue with authentication on a third party's WCF service. I don't know how it's configured, it's like a black box for me. The only thing that I know, that those webservice should use Basic authentication, but may not.
I've added fiddler, and even wireshark to analyze what's happening inside of those requests, and found out that requests with authorization header do get authenticated. So basically, using a SoapUI I was able to authenticate on those WCF service.
I've generated a test client using svcutil and specified config file like this:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_1" useDefaultWebProxy="false" >
<security mode="Message" >
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://theurl.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_1"
contract="CA_TestMediaSaturn.IDCIntegration" name="BasicHttpBinding_2" />
</client>
Also I've added authorization information to client in code file:
client.ClientCredentials.UserName.UserName = "one";
client.ClientCredentials.UserName.Password = "two";
But I wasn't able to get those Authorization header encoded in base64.
I wonder how can I configure my client to obtain those header in order to get authorized on webservice side. I did found an article describing how to make it on your own. But maybe there is a way to make it a lot easier?
UPDATE 1:
I've just receiver service configuration settings from 3rd party vendor. Mb it can somehow help in finding out the reason of error.
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_1" >
<security mode="TransportCredentialOnly">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
you should set mode="Transport" instead of "Message". This will generate Authorization header. current setting is message security so authentication is inside SOAP.
EDIT: seems like you need pre-authenitcate.
in general wcf will first not send authorization header, and if the service returns a challenge to do it then it will send the message again with the header. some servers do not support this challenge mechanism and will require to send authorization header already at first shot. this is called pre authentication in .net 2. unfortunetely wcf does not support it. but you could do it yourself: first set security mode to None so WCF will not send security at all. then see example here how to add this header yourself to the wcf call.
I am creating a web service that will be consumed by a single client in another part of the world. I don't have any knowledge or control over the technology they are using but have been asked to
"use SSL to encrypt the message during transport and use UsernameToken
for client authentication"
I'm planning to use WCF4 to create the service and know generally how to set this all up. However I'm struggling to find the correct configuration for bindings etc. Google gives me lots of results around WSE 3.0 but I'm pretty sure (please correct me if I'm wrong) that I shouldn't be using WSE for a WCF service.
This article initially seems to suggest I should be using a custom binding but then also says I should "consider using the WCF system-defined bindings with appropriate security settings instead of creating a custom binding". However I can't see any examples of what this should be.
I would be grateful if anyone can point me in the right direction.
tl;dr: What are the WCF4 config settings to support SSL and UsernameToken?
Take a look at the WsHttpBinding. You can use a security mode of TransportWithMessageCredential to use SSL and a message credential of UserName. If you are hosting in IIS set up SSL there.
You can set up the binding in config as follows.
<bindings>
<wsHttpBinding>
<binding name="secureBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
You can then use this binding config as follows
<services>
<service name="ServiceName">
<endpoint address="" binding="wsHttpBinding" contract="ContractType" bindingConfiguration="secureBinding" />
</service>
</services>
Both these elements are children of the system.serviceModel element in config.
I'm writing a C# WCF service that publishes an endpoint using a WSHttpFederationBinding. We have our own security token server providing tokens, for which callers need to use a custom binding.
This is all working fine for a C# client I've written: this has a custom binding in its app.config like so:
<bindings>
<customBinding>
<binding name="CustBind">
<security authenticationMode="UserNameForCertificate" requireDerivedKeys="true"
messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"
requireSecurityContextCancellation="false"
requireSignatureConfirmation="false">
<secureConversationBootstrap/>
</security>
<httpTransport/>
</binding>
</customBinding>
<wsFederationHttpBinding>
<binding name="FedBind">
<security>
<message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
negotiateServiceCredential="false">
<issuer address="http://STSHost/MySTS" binding="customBinding"
bindingConfiguration="CustBind">
<identity>
<certificateReference x509FindType="FindBySubjectName" findValue="localhost"/>
</identity>
</issuer>
</message>
</security>
</binding>
</wsFederationHttpBinding>
</bindings>
However, what I want is for users to be able to generate their own clients in whatever language they want, just given the WSDL that the WCF service publishes. The problem with this is that when I try such a thing with Developer Studio's "Add Service Reference" functionality, the resulting client doesn't work.
The reason it doesn't work is because the generated client's app.config is clearly wrong: while the STS is there in the "issuer" element, there's no sign of the custom binding. Looking at the WSDL this isn't too surprising, as there's no mention of anything there other than the issuer address.
Is there any way to get WCF to add something to the WSDL to describe this situation? My server's app.config bindings look okay to me: the "issuer" element is exactly the same as for the working client, including the address and details of the custom binding. Does anyone know why WCF seems to be ignoring this when generating the WSDL?
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.
I am using a WCF service and a net.tcp endpoint with serviceAuthentication's principal PermissionMode set to UseWindowsGroups.
Currently in the implementation of the service i am using the PrincipalPermission attribute to set the role requirements for each method.
[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string method1()
I am trying to do pretty much the same exact thing, except have the configuration for the role set in the app.config. Is there any way to do this and still be using windows groups authentication?
Thanks
If you are hosting your WCF service in IIS, it will run in the ASP.NET worker process, which means you can configure authentication and authorization as you would do with ASMX web services:
<system.Web>
<authentication mode="Windows"/>
<authorization>
<allow roles=".\Administrators"/>
<deny users="*"/>
</authorization>
</system.Web>
Then you will have to disable anonymous access to your endpoint in IIS, and instead enable Windows Integrated Authentication.In the IIS management console you do that by bringing up the 'Properties' dialog for your virtual directory. You will then find the security settings in the 'Directory Security' tab.
Of course, the only communication channel available will be HTTP. Clients will have to provide their Windows identity in the request at the transport-level with these settings:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WindowsSecurity">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost/myservice"
binding="wsHttpBinding"
bindingConfiguration="WindowsSecurity"
contract="IMyService" />
</client>
</system.serviceModel>
Note that if your service endpoint uses wsHttpBinding then you will also have to add SSL to your endpoint since that's a requirement enforced by WCF when you using transport-level security.
If you instead go for the basicHttpBinding, you are then able to use a less secure authentication mode available in WCF called TransportCredentialOnly, where SSL is no longer required.
For more detailed information, here is a good overview of the security infrastructure in WCF.
Lars Wilhelmsen has posted a solution for this problem. Have a look at
http://www.larswilhelmsen.com/2008/12/17/configurable-principalpermission-attribute/
If I understood well you want to select the role at runtime. This can be done with a permission demand within the WCF operation. E.g.
public string method1()
{
PrincipalPermission p = new PrincipalPermission(null, "Administrators");
p.Demand();
...