none
Expose WCF Endpoints with REST and SOAP using authentication with simplified configuration RRS feed

  • Question

  • As usual, trying to find good examples to do exactly what I want is proving difficult.

    I've written a WCF Service in .NET 4.5 with simplified configuration, so I've got no services section in the configuration file.

    I want to provide SOAP and REST APIs.  I also need to restrict access by username and password and I've written a class derived from UserNamePasswordValidator that handles this.

    By importing the service reference into a desktop app I can call the service using this code:

        var svc = new MyUserService.UserServiceClient();
        svc.ClientCredentials.UserName.UserName = "TestApp";
        svc.ClientCredentials.UserName.Password = "******";

    I expect to be able to call the service from Javascript using something like this:

        $.ajax({
     url: 'https://domain.userservice.svc',
     type: 'GET',
     contentType: "application/json",
     success: function(data){
     },
     data: requestData,
     headers: {
    User: "TestApp",
    Password: "********"
     }
        });

    Here's the config file so far, with the SOAP service working.

        <system.serviceModel>
          <bindings>
            <wsHttpBinding>
              <binding name="wsHttpBindingConfig">
                <security mode="TransportWithMessageCredential">
                  <message clientCredentialType="UserName" />
                </security>
              </binding>
            </wsHttpBinding>
          </bindings>
          <behaviors>
            <serviceBehaviors>
              <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                  <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyAuthenticationModule.Security.WcfUsernameValidator, MyAuthenticationModule.Security" />
                  <serviceCertificate findValue="TestSelfSigned" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
                </serviceCredentials>
              </behavior>
            </serviceBehaviors>
          </behaviors>
          <protocolMapping>
            <add scheme="http" binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConfig" />
          </protocolMapping>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        </system.serviceModel>

    By blindly following examples from around the web I ended up with this:

        <system.serviceModel>
          <bindings>
            <wsHttpBinding>
              <binding name="wsHttpBindingConfig">
                <security mode="TransportWithMessageCredential">
                  <message clientCredentialType="UserName" />
                </security>
              </binding>
            </wsHttpBinding>
            <webHttpBinding>
              <binding name="webHttpBindingJson">
                <security mode="None" />
              </binding>
            </webHttpBinding>
          </bindings>
          <behaviors>
            <serviceBehaviors>
              <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                  <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyAuthenticationModule.Security.WcfUsernameValidator, MyAuthenticationModule.Security" />
                  <serviceCertificate findValue="TestSelfSigned" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
                </serviceCredentials>
              </behavior>
            </serviceBehaviors>
            <endpointBehaviors>
              <behavior name="jsonEndpointBehaviour">
                <enableWebScript/>
              </behavior>
              <behavior name="poxEndpointBehaviour">
                <webHttp/>
              </behavior>
            </endpointBehaviors>
          </behaviors>
          <protocolMapping>
            <add scheme="http" binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConfig" />
            <add scheme="httpJson" binding="webHttpBinding" bindingConfiguration="webHttpBindingJson"/>
          </protocolMapping>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        </system.serviceModel>

    I don't think that I'm too far from it, but I know I'm not there.  Can someone finish of the configuration, or point me in the right direction?  What url will I need to call from JavaScript?

    If I were to add a Web API to support the REST service then I could handle the cross origin issues by catching the request in Global.asax.  How will I handle cors in the WFC service.

    And a bonus question... I wanted to test the username on my dev machine / password authentication without having to install a certificate and go to https, and apply https later on the deployed site, but this doesn't look possible.  Am I correct?

    Thanks for helping...

    Saturday, June 13, 2015 4:55 PM

Answers

All replies

  • Hi David1936,

    If you want to call the WCF Service from the Javascript, I will recommend you use the WCF Rest Service, it will make it very easy to consume the WCF Service using the Javascript.
    If you want to use the username and password authentication, in your sevice side you should install the service certificate, after that you can give the correct username and password in your client side without installing certificate to access the WCF Service.
    For more information, please try to refer to the following articles:
    #An Introduction to Restful Service with WCF:
    https://msdn.microsoft.com/en-us/magazine/dd315413.aspx.

    #Enabling CORS in WCF:
    http://www.codeproject.com/Articles/845474/Enabling-CORS-in-WCF .

    #Call a WCF Rest service from Javascript:
    http://www.codeproject.com/Articles/722874/Post-JSON-data-to-WCF-RESTful-Service-using-jQuery.

    #Authentication on a WCF Rest Service:
    http://www.codeproject.com/Tips/838957/WCF-Restful-Service-Form-Authentication .

    Best Regards,
    Amy Peng


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, June 16, 2015 2:29 AM
    Moderator
  • Thank you for your answer.

    The issue with the links that you have provided, and many others that I've found on the web is where the service functions are decorated with JSON specific attributes, e.g.

    [WebInvoke(UriTemplate = "/TestMethod", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json

    [WebInvoke(Method = "POST",
                        RequestFormat = WebMessageFormat.Json,
                        ResponseFormat = WebMessageFormat.Json,
                        UriTemplate = "SaveBook/{id}")]

    To me, this goes against what WCF should do, and indeed against what I want to do, i.e. call the same service from varied clients that might require either SOAP or JSON data.  Doesn't decorating the methods like this mean that they will only return JSON data?

    To my way of thinking, what I want to do is create separate end points, one for SOAP and one for JSON.  These end points will then forward the call to the same service and return the data in whatever format they are configured for.  This is what I've been trying to achieve with my configuration.

    I haven't been able to find any samples that help me to do this that support authentication and CORS too.

    I hope that you can help.

    Tuesday, June 16, 2015 1:52 PM
  • Hi David1936,

    >>To my way of thinking, what I want to do is create separate end points, one for SOAP and one for JSON.  These end points will then forward the call to the same service and return the data in whatever format they are configured for.  This is what I've been trying to achieve with my configuration.

    Yes, it is a good way to create separate soap and rest endpoints for different requirement, the following articles will tell you how to achieve it, please try to refer to:
    #How to enable REST and SOAP both on the same WCF Service:
    http://debugmode.net/2011/12/22/how-to-enable-rest-and-soap-both-on-the-same-wcf-service/ .
    #Exposing WCF services with SOAP and REST endpoints:
    https://jaysongo.wordpress.com/2013/01/02/exposing-wcf-services-with-soap-and-rest-endpoints/ .

    >>I haven't been able to find any samples that help me to do this that support authentication and CORS too.

    For how to use authentication in WCF, please try to refer to the following article:
    #Secure Self-Hosted WCF REST Services with a Custom UserNamePasswordValidator:
    https://www.develop.com/secure-self-hosted-wcf-rest-services-with-a-custom-usernamepasswordvalidator .

    For how to enable the CORS in the WCF Service, please try to refer to the following articles:
    #Enabling CORS in WCF:
    http://www.codeproject.com/Articles/845474/Enabling-CORS-in-WCF .
    #CORS Support within WCF REST Services:
    http://stackoverflow.com/questions/7234599/cors-support-within-wcf-rest-services .

    Best Regards,
    Amy Peng



    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Tuesday, June 23, 2015 9:28 AM
    Moderator