Securing WCF service endpoint with custom authentication

authentication, endpoint, wcf

Solution

I want to secure some endpoint of a WCF service, i dont know if you can secure some endpoint and some not.

Sure - you just need to create two separate binding configurations, and use one on those endpoints that are secured, the other on the others:

<bindings>
  <basicHttpBinding>
    <binding name="secured">
      <security mode="Message">
        <message ...... />
      </security>
    </binding>
    <binding name="unsecured">
      <security mode="None" />
    </binding>
  </basicHttpBinding>
</bindings>
<services>
  <service name="WindowsFormsApplication11.WmsStatService" behaviorConfiguration="mex">
    <host>
      <baseAddresses>
        <add baseAddress="http://192.168.0.199:87" />
      </baseAddresses>
    </host>        

    <endpoint address="/Secured/Test" 
              binding="basicHttpBinding" bindingConfiguration="secured" 
              contract="WindowsFormsApplication11.IWmsStat" 
              behaviorConfiguration="MyServiceBehavior" />

    <endpoint address="/Unsecured/Test" 
              binding="basicHttpBinding" bindingConfiguration="unsecured" 
              contract="WindowsFormsApplication11.IWmsStat" 
              behaviorConfiguration="MyServiceBehavior" />

    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>

Marc

PS: not sure if that's just a problem with your postings not being up to date anymore - have you noticed, that you have two separate behavior configurations:

<behaviors>
    <serviceBehaviors>
      <behavior name="mex">
        <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
      </behavior>
      <behavior name="MyServiceBehavior">
        <serviceCredentials>
          <userNameAuthentication 
               userNamePasswordValidationMode="Custom" 
                customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" />
        </serviceCredentials>
      </behavior>
   </serviceBehaviors>      
</behaviors>

and your service is only referencing the "mex" behavior? That means, your service is indeed using the `<serviceMetadata>` behavior - but NOT the `<serviceCredentials>` one!

You need to merge these into one and then reference just that:

<behaviors>
    <serviceBehaviors>
      <behavior name="Default">
        <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
        <serviceCredentials>
          <userNameAuthentication 
               userNamePasswordValidationMode="Custom" 
                customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" />
        </serviceCredentials>
      </behavior>
   </serviceBehaviors>      
</behaviors>
<services>
    <service name="...." behaviorConfiguration="Default" 

Marc

Problem

I want to secure some endpoint of a WCF service, i dont know if you can secure some endpoint and some not. Below I have the stripped WCF service (self hosted). The same WCF serves also the CA Policy file. If I secure this WCF service or some endpoints of ut the CA Policy part must not ask me a username password. The policy file must be accessible all the time. Is that also possible? I found alot WCF custom blogs/postings. There are alot of ways to do security. All I want is that I can secure some endpoints with username/password but the credentials must not be visible with tools like Fiddler. The data however it can be visible in this case. I implemented already a Customvalidator but the app.config file is also importent to define things. And I am not very good at that. ``` namespace WindowsFormsApplication11 { public partial class Form1 : Form { public ServiceHost _host = null; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // Create a ServiceHost for the CalculatorService type and // provide the base address. _host = new ServiceHost(typeof(WmsStatService)); _host.AddServiceEndpoint(typeof(IPolicyProvider), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior()); _host.Open(); } } // Define a service contract. [ServiceContract(Namespace = "http://WindowsFormsApplication11")] public interface IWmsStat { [OperationContract] string getConnectedViewers(string channelName); [OperationContract] string sayHello(string name); } [ServiceContract] public interface IPolicyProvider { [OperationContract, WebGet(UriTemplate = "/ClientAccessPolicy.xml")] Stream ProvidePolicy(); } //[DataContract] public class Ads { // [DataMember] public string AdFileName { get; set; } //[DataMember] public string AdDestenationUrl { get; set; } public string ConnectedUserIP { get; set; } } // public class CustomValidator : UserNamePasswordValidator { public override void Validate(string userName, string password) { if(null == userName || null == password) { throw new ArgumentNullException(); } if(userName == "Oguz" && password == "2009") { return; } FaultCode fc = new FaultCode("ValidationFailed"); FaultReason fr = new FaultReason("Good reason"); throw new FaultException(fr,fc); } } // public class WmsStatService : IWmsStat, IPolicyProvider { public string sayHello(string name) { return "hello there " + name + " nice to meet you!"; } public Stream ProvidePolicy() { WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml"; return new MemoryStream(File.ReadAllBytes("ClientAccessPolicy.xml"), false); } public string getConnectedViewers(string channelname) { // do stuff return null; } } } ``` The app.config. This config file does not work. I wanted to put the custom authentication for a endpoint. I have no clue. ``` <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="WindowsFormsApplication11.WmsStatService" behaviorConfiguration="mex"> <host> <baseAddresses> <add baseAddress="http://192.168.0.199:87" /> </baseAddresses> </host> <endpoint address="http://192.168.0.199:87/Test" binding="basicHttpBinding" bindingConfiguration="" contract="WindowsFormsApplication11.IWmsStat" behaviorConfiguration="MyServiceBehavior" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <!--<bindings> <wsHttpBinding> <binding name="wshttp"> <security mode="Message"> <message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding> </bindings>--> <behaviors> <serviceBehaviors> <behavior name="mex"> <serviceMetadata httpGetEnabled="true" httpGetUrl=""/> </behavior> <behavior name="MyServiceBehavior"> <serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration> ```

Original source