Search code examples
wcfiishttpspermissionslocation

IIS hosted WCF Https using tag Location to control Access to different Endpoint


I got a task to setup WCF in IIS and need control access to different endpoint with different set of users. I am able to setup https. While I try to set permission with tag <location> in IIS, it seems not working.

I have two usernames, one is xxx.luo and another is xxx.luo2. I like Service1.csv only accessible by xxx.luo and Service2.svc for xxx.luo2. But in following config, I can only get xxx.luo to have access to both endpoint.

For xxx.luo2, I always get following error message:

"The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'. The remote server returned an error: (401) Unauthorized."

Will you have any suggestions? Is it possible to control permission in this way?

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.6.1" />
    <httpRuntime targetFramework="4.6.1" />
  </system.web>
  <system.serviceModel>
    <bindings>
          <basicHttpBinding>  
        <binding name="secureHttpBinding">  
          <security mode="Transport">  
            <transport clientCredentialType="Windows" />  
          </security>  
        </binding>  
      </basicHttpBinding> 
    </bindings>
    <services>
  
      <service name="WcfService1.Service1">  
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="WcfService1.IService1" />  
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />  
      </service>  

      <service name="WcfService1.Service2">  
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="WcfService1.IService2" />  
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />  
      </service>  
      
    </services>
    <behaviors>
      <serviceBehaviors>  
        <behavior>  
          <serviceMetadata httpsGetEnabled="true" />  
          <serviceDebug includeExceptionDetailInFaults="false" />  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
      <security>
        <authentication>
            <anonymousAuthentication enabled="false" />
            <windowsAuthentication  enabled="true"/>
        </authentication>
        <authorization>
            <remove users="*" roles="" verbs="" />
            <add accessType="Allow" roles="xxx.luo"/>
        </authorization>
    </security>
  </system.webServer>
<location path="Default Web Site/Service2.svc" allowOverride="false" inheritInChildApplications="false">
      <system.webServer>
              <security>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <windowsAuthentication  enabled="true"/>
                </authentication>
                <authorization>
                    <remove users="*" roles="" verbs="" />
                    <add accessType="Allow" roles="xxx.luo2"/>
                </authorization>
            </security>
      </system.webServer>
    </location>
</configuration>

Solution

  • With the help of a colleague who already have lots stackoverflow reputation, I(he) figure out the solution.

    1. I need set both my username xxx.luo and xxx.luo2 has access to both pages in tag <system.webServer>
    2. In tag <location> for page Service1.svc, I remove access of xxx.luo2
    3. In tag <location> for page Service2.svc, I remove access of xxx.luo

    The web.config as following:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.6.1" />
        <httpRuntime targetFramework="4.6.1" />
      </system.web>
      <system.serviceModel>
        <bindings>
              <basicHttpBinding>  
            <binding name="secureHttpBinding">  
              <security mode="Transport">  
                <transport clientCredentialType="Windows" />  
              </security>  
            </binding>  
          </basicHttpBinding> 
        </bindings>
        <services>
      
          <service name="WcfService1.Service1">  
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="WcfService1.IService1" />  
            <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />  
          </service>  
    
          <service name="WcfService1.Service2">  
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureHttpBinding" contract="WcfService1.IService2" />  
            <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />  
          </service>  
          
        </services>
        <behaviors>
          <serviceBehaviors>  
            <behavior>  
              <serviceMetadata httpsGetEnabled="true" />  
              <serviceDebug includeExceptionDetailInFaults="false" />  
            </behavior>  
          </serviceBehaviors>  
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
          <security>
            <authentication>
                <anonymousAuthentication enabled="false" />
                <windowsAuthentication  enabled="true"/>
            </authentication>
            <authorization>
                <remove users="*" roles="" verbs="" />
                <add accessType="Allow" users="xxx.luo"/>
                <add accessType="Allow" users="xxx.luo2"/>
            </authorization>
        </security>
      </system.webServer>
      
      <location path="Service1.svc" >
        <system.web>
          <authorization>
            <deny users="companydomain\xxx.luo" />
          </authorization>
        </system.web>
      </location> 
    
      <location path="Service2.svc" >
        <system.web>
          <authorization>
            <deny users="companydomain\xxx.luo2" />
          </authorization>
        </system.web>
      </location> 
    </configuration>