Struggling to secure WCF Service

Discussion in 'Site Programming, Development and Design' started by MarkP, Sep 10, 2010.

  1. I've got a WCF Service hosted at Winhost. I need to call this from an asp.net website (also hosted on the same domain) and also from remote windows forms applications.

    When I use WsHttpBinding with Security="None" everything works fine.

    However "no security" will certainly not be acceptable when this goes live...


    Originally in the development setup I used custom X.509 certificates which seemed to work well, however we can't use these with Winhost.

    I have purchased an SSL certificate for the domain and am hoping to use UserName/Password over https both for the windows forms clients and the asp.net client.

    I have an asp.net membership provider database setup which is working from the asp.net website point of view, and I would like to use the same database (with roles) to control access to the WCF service.

    Can anyone point in me in the right direction to achieve this?

    eg basicHttpBinding or WsHttpbinding?
    Transport or Message security mode?
    Which clientCredentialType?
    Do I specify: http://mydomain/service.svc or https://mydomain/service.svc as the base address?

    I have tried dozens of different combinations of the above and all of them end up producing errors.

    I guess I'm hoping someone has already implemented this and can advise on the best set up.

    Thanks in advance,

    MarkP
     
    Last edited by a moderator: Oct 14, 2015
  2. Ray

    Ray

    I'm a little confused on what you are trying to do. So, from what you said, you are trying to protect your web service with some kind of forms authentication, is that correct?

    What is the error you are getting?
     
  3. Yes, that's it.

    (Well the ultimate goal is to restrict access to the web service to authorised people only. If there's a better way I'm open to any suggestions.)


    As for the error, well I've tried dozens of combinations of bindings / security modes and had dozens of different errors. I figured it was just easier to ask what was a right way of doing it rather than confuse people with lots of ways that don't work.

    I guess I'm just after the simplest way - am sure someone will already have got something similar working!

    (But if you want me to post some of the errors and non-working configs then I'm happy to do so.)

    Thanks,
    MarkP
     
  4. Ray

    Ray

    Last edited by a moderator: Oct 14, 2015
  5. Yes, I've implemented Forms authentication with ASP.net membership provider.

    This is working for the website. ie a user can log into the website successfully and then see parts of the website that are restricted to authorised users.

    However so far I haven't been able to restrict calls to the WCF service in the same way.

    I'm currently experimenting with a web.config file for the service along these lines:


    Code:
    <system.serviceModel>
    
      <serviceHostingEnvironment>
        <baseAddressPrefixFilters>
          <add prefix="http://myDomain.com/wcf"/>
        </baseAddressPrefixFilters>
      </serviceHostingEnvironment>
    
      <bindings>
        <wsHttpBinding>
          <binding name="TransportSecurity">
            <security mode="TransportWithMessageCredential">
              <message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false"/>
            </security>
          </binding>
        </wsHttpBinding>
        <mexHttpBinding>
          <binding name="NewBinding0" />
        </mexHttpBinding>
      </bindings>
      
      <services>
        <service behaviorConfiguration="ServiceBehavior" name="MyFirstWCF.MyService1">
          <endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransportSecurity"
            contract="MyFirstWCF.IMyService1" />
          <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="NewBinding0"
            contract="IMetadataExchange">
    
            <identity>
              <dns value="localhost" />
            </identity>
          </endpoint>
          <host>
            <baseAddresses>
              <add baseAddress="http://myDomain.com/wcf/Service.svc" />
            </baseAddresses>
          </host>
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="ServiceBehavior">
            <serviceMetadata httpGetEnabled="true" httpGetUrl="http://myDomain.com/wcf/Service.svc"
              httpsGetEnabled="false" />
            <serviceDebug includeExceptionDetailInFaults="true" />
            <serviceAuthorization principalPermissionMode="UseAspNetRoles"></serviceAuthorization>
            <serviceCredentials>
              <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="MyMembershipProvider" />
            </serviceCredentials>
          </behavior>
        </serviceBehaviors>
      </behaviors>
    
    </system.serviceModel>
    
    But when I try to call this from the client I get:

    "The remote server returned an unexpected response: (405) Method not allowed."


    I'm wondering if I have to somehow explicitly state role permissions in the service itself....

    Or I could be completely on the wrong course!


    Thanks,
    Mark
     
  6. Ray

    Ray

    Try adding this line in the web service web.config file.

    <system.web>
    <authorization>
    <deny users="?"/>
    </authorization>
    </system.web>
     
  7. I've tried that, unfortunately same error message.


    However I have now finally got it going....!


    The endpoint in the client had to be changed from:

    https://mydomain.com/wcf/
    to
    https://mydomain.com/wcf/Service.svc

    Which sounds kind of obvious.... ...but I'm sure it had worked previously with the original endpoint when security was set to "None".

    Interestingly in the <baseAddressPrefixFilters> I have got
    <add prefix ="http://mydomain.com/wcf">

    But it the <services> section I have got the <baseAddress> set as:
    https://mydomain.com/wcf/Service.svc
    (ie with the https and the full uri.)

    I'm not entirely sure how WCF operates it's logic on the various addresses, I just kept trying different options until it worked.... Maybe this will help someone else at some point.


    Thanks,
    MarkP
     
  8. Thanks for the follow up explanation. It's going to save someone a headache for sure.
     

Share This Page