WCF Security Guidance Package and MultiEndpoints

Topics: Service Factory Modeling Edition Forum
Apr 16, 2009 at 4:45 PM
If I create a Service with two Endpoints - SQLServerEndpoint and WindowsAccountEndpoint.
Run recipe Service Factory (WCF Security) -> Secure a service using Direct Authentication with Sql Server for the Endpoint "SQLServerEndpoint" 
Run recipe Service Factory (WCF Security) -> Secure a service using Direct Authentication with Windows account for the Endpoint "WindowsAccountEndpoint".

When I look at the web.config file the Endpoints are properly defined.
<endpoint address="SQLServer" binding="basicHttpBinding" name="SQLServerEndpoint"
                bindingNamespace
=http://rfg.realogy.com/HouseManagement/Services/2009/02
                contract
="RFG.House.Svc.WCF.ServiceContracts.IHouseManagementServiceContract"/>
<endpoint address="WindowsAccount" binding="basicHttpBinding" name="WindowsAccountEndpoint"
                bindingNamespace
=http://rfg.realogy.com/HouseManagement/Services/2009/02
                contract
="RFG.House.Svc.WCF.ServiceContracts.IHouseManagementServiceContract"/>


The ServiceBehaviors are also properly defined.
<serviceBehaviors>
   <behavior name="DirectAuthenticationUserNameTokenSQL">
      <
serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
         <serviceCertificate findValue="CN=PLWXP1.rfg.corp.rlg" storeLocation="LocalMachine"
                                      storeName
="My" x509FindType="FindBySubjectDistinguishedName"/>
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlProvider"/>
         </serviceCredentials>
         <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlProvider"/>
   </behavior>
   <behavior name="DirectAuthenticationUserNameTokenWindows">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
         <serviceCertificate findValue="CN=PLWXP-MILCHMAR1.rfg.corp.rlg" storeLocation="LocalMachine"
                                      storeName
="My" x509FindType="FindBySubjectDistinguishedName"/>
         <windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false"/>
      </serviceCredentials>
      <serviceAuthorization principalPermissionMode="UseWindowsGroups" impersonateCallerForAllOperations="false"/>
   </behavior>
</serviceBehaviors>

My question is in regards to the <service> element
<service behaviorConfiguration="DirectAuthenticationUserNameTokenSQL"
                name="RFG.House.Svc.WCF.ServiceImplementation.HouseManagementService">

It seems I can olny associate a single behavior with the service. However the SQLServerEndpoint needs to use DirectAuthenticationUserNameTokenSQL behavior and WindowsAccountEndpoint needs to use DirectAuthenticationUserNameTokenWindows behavior. Otherwise I can only get one of the Endpoints to Authenticate at a time without changing the service behaviorConfiguration value in the web.config file.

On the client side I am able to associate the Endpoint with the proper behavior because on the client side they are <endpointBehaviors> and not
<serviceBehaviors> like on the server side.

So my question is can I have a service with two Endpoints where each Endpoint has a diffrent WCF Security Setting associated with it such
that both Endpoints will be available to clients at the same time. Internal Users use WindowsAccountEndpoint and external Users use SQLServerEndpoint.

Thanks
Developer
Apr 16, 2009 at 6:18 PM
On the server side you can only have behaviors at the service level (not endpoint) so the options are:
1) Have a behavior with the settings required by all the endpoints in that service (assuming they are compatible)
2) Create a separate service for each endpoint and therefore have different behaviors for each service.

In you case, I think that you may use #1 with both service certificates and the rest of the common settings.
Apr 16, 2009 at 6:35 PM

Problem is the two behaviors have two different values for the same attribute principalPermissionMode:

<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlProvider" />
<
serviceAuthorization principalPermissionMode="UseWindowsGroups" impersonateCallerForAllOperations="false" />

 

Developer
Apr 16, 2009 at 7:26 PM
Edited Apr 16, 2009 at 7:28 PM
Well that's true.
Did you try using endpoint behaviors? (Same as client side) and place the behavior element in an EndpointBehaviors section.
And don't forget to remove the behaviorConfiguration from the service element. 
Like this:

<endpoint address="SQLServer" binding="basicHttpBinding" name="SQLServerEndpoint" 
                     behaviorConfiguration="DirectAuthenticationUserNameTokenSQL"
                bindingNamespace
=http://rfg.realogy.com/HouseManagement/Services/2009/02
                contract
="RFG.House.Svc.WCF.ServiceContracts.IHouseManagementServiceContract"/>
<endpoint address="WindowsAccount" binding="basicHttpBinding" name="WindowsAccountEndpoint" 
                     behaviorConfiguration="DirectAuthenticationUserNameTokenWindows"
                bindingNamespace
=http://rfg.realogy.com/HouseManagement/Services/2009/02
                contract
="RFG.House.Svc.WCF.ServiceContracts.IHouseManagementServiceContract"/>

<endpointBehaviors>
   <behavior name="DirectAuthenticationUserNameTokenSQL">
      <
serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
         <serviceCertificate findValue="CN=PLWXP1.rfg.corp.rlg" storeLocation="LocalMachine"
                                      storeName
="My" x509FindType="FindBySubjectDistinguishedName"/>
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlProvider"/>
         </serviceCredentials>
         <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlProvider"/>
   </behavior>
   <behavior name="DirectAuthenticationUserNameTokenWindows">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
         <serviceCertificate findValue="CN=PLWXP-MILCHMAR1.rfg.corp.rlg" storeLocation="LocalMachine"
                                      storeName
="My" x509FindType="FindBySubjectDistinguishedName"/>
         <windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false"/>
      </serviceCredentials>
      <serviceAuthorization principalPermissionMode="UseWindowsGroups" impersonateCallerForAllOperations="false"/>
   </behavior>
</endpointBehaviors>

Apr 16, 2009 at 7:40 PM
I had thought of that and tried it but got errors for almost all the elements.
How <behavior> is constructed under <endpointBehaviors> differs greatly from <serviceBehaviors>.

Under <endpointBehaviors> get errors:
The element 'behavior' has invalid child element 'serviceMetadata'
The element 'behavior' has invalid child element 'serviceDebug'
The element 'behavior' has invalid child element 'serviceCredentials'
The element 'behavior' has invalid child element 'serviceAuthorization'
Developer
Apr 17, 2009 at 1:29 PM
In this case then I would try separating the endpoints in two services with each behavior and endpoint.