locked
Configuring secure service endpoint using wsHttpBinding and Message Security using protocol HTTP RRS feed

  • Question

  • User201331998 posted

    I have a legacy WCF service with 2 endpoints. One endpoint is configured using basicHttpBinding and it works fine.  I would like to configure the other endpoint to use wsHttpBinding and set the security mode to TransportWithMessageCredentials so that I can read the user name using:

    string UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;

    The protocol has to be HTTP and not use the secure HTTPS.
    I found an answer similar to this problem and tried implementing it.  This is the web.config file:

        <bindings>
            <basicHttpBinding>
              <binding name="myBindingConfiguration1" closeTimeout="00:01:00">
                <security mode="None">
                  <transport clientCredentialType="None" />
                </security>
              </binding>
            </basicHttpBinding>
            <wsHttpBinding>
              <binding name="SecureServiceEndpoint"  closeTimeout="00:01:00">
                <security mode="None">
                </security>
              </binding>  
            </wsHttpBinding>
            <customBinding>
              <binding name="HttpWithAuthentication">
                <security authenticationMode="UserNameOverTransport" allowInsecureTransport="true" />
                <context />
                <!-- needed for durable worklfows -->
                <textMessageEncoding messageVersion="Soap12Addressing10" />
                <httpTransport />
              </binding>
            </customBinding>
          </bindings>
            <services>
              <service behaviorConfiguration="ServiceBehavior" name="Service.Service">
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <endpoint address="insecure" binding="basicHttpBinding" bindingConfiguration="myBindingConfiguration1"
                  name="InsecureService" contract="Service.IService" />
                <endpoint address="secure" binding="customBinding" bindingConfiguration="HttpWithAuthentication"
                  name="SecureService" contract="Service.ISecureService" />
              </service>
            </services>
    

    When I try to update the service reference, I get the error:
       messageVersion="Soap12Addressing10" is not a valid instance of type.

    According to the MS documentation, this is a valid type.
    What message version should this attribute be?

    I tried removing this attribute and the service reference can be updated but when accessing the secure endpoint, the client application throws an exception:
       "The provided URI scheme 'http' is invalid; expected 'https'.\r\nParameter name: via".

    I have read in the documentation that this approach is not recommended but this is a legacy application. 

    Is it possible to use TransportWithMessageCredentials while using the HTTP protocol?

    If it is possible can tell me why this is not recommended, I will be sure to explain it to my superiors.

    EDIT:

    I was able to update the service reference by changing the binding as follows:

    <wsHttpBinding>
          <binding name="PaymentSecureServiceEndpoint"  closeTimeout="00:01:00">
            <security mode="Message">
            </security>
          </binding>  
    </wsHttpBinding>

    I set the username in the client application using this line of code:

    Service.ClientCredentials.UserName.UserName = "Test Client";

    However, the PrimaryIdentity.Name value is still null when I check it in the web service.

    How do you get the user name in the web service!?!?!?

    EDIT

    I am able to the the value of the PrimaryIdentity.Name by using the following binding:

    <wsHttpBinding>
          <binding name="PaymentSecureServiceEndpoint"  closeTimeout="00:01:00">
            <security mode="Message">
            </security> 
          </binding>  
        </wsHttpBinding>

    However, the value is my username.

    This web service is a legacy application and this value was expected to be the client application name:

     string ApplicationID = ServiceSecurityContext.Current.PrimaryIdentity.Name;

    Is there any way that I can pass the name of the client application to the web service, securely.

    There is a method that passes the application ID as a parameter to the web service.

    Is there any way to more securely pass the name of the application to the web service.

    I set the client credentials on the client side but I cannot access the UserName on the web service side.


    Thanks.

    Wednesday, February 19, 2014 12:28 PM

Answers

  • User201331998 posted

    I was finally able to figure out how to implement Message Security using a custom user name authentication.  It needed a service certificate.  To add one to your local machine to test your service is not trivial.  This is the website with the instructions:

    http://msdn.microsoft.com/en-us/library/ff647171.aspx

    Thanks for all of your help!

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 26, 2014 1:55 PM

All replies

  • User-417640953 posted

    Is it possible to use TransportWithMessageCredentials while using the HTTP protocol?

    Hi gloria10,

    Thanks for your post.

    As we all know that When setting the security mode to TransportWithMessageCredential,

    the transport determines the actual mechanism that provides the transport-level security.

    For example, the HTTP protocol uses Secure Sockets Layer (SSL) over HTTP (HTTPS). Therefore, setting the ClientCredentialType

    property of any transport security object (such as HttpTransportSecurity) is ignored.  In other words, you can only set

    the ClientCredentialType of the message security object (for the WSHttpBinding binding, the NonDualMessageSecurityOverHttp object).

    Please get more information from article How to: Use Transport Security and Message Credentials below.

    http://msdn.microsoft.com/en-us/library/ms789011(v=vs.110).aspx

    Hope this helps, thanks.

    Best Regards!

    Friday, February 21, 2014 1:26 AM
  • User201331998 posted

    Thanks for replying.

    As you could guess, I am new to writing secure web services.  I have read a lot about setting the configuration file with these security elements and attributes.  But I am still learning.  So I apologize, in advance, for asking some basic questions.

    I got a value assigned to the ApplicationID in the web service application:

    string ApplicationID = ServiceSecurityContext.Current.PrimaryIdentity.Name;

    by using this binding configuration:

    <wsHttpBinding>
          <binding name="ServiceEndpoint"  closeTimeout="00:01:00">
            <security mode="Message">
            </security> 
          </binding>
    </wsHttpBinding>

    However, the value stored in

    ServiceSecurityContext.Current.PrimaryIdentity.Name;

    is my User Name for Windows Authentication in my SQL Server 2012 Management Studio.

    According to the documentation for this class should be identifying the client application:

    "Represents the security context of a remote party. On the client, represents the service identity and, on the service, represents the client identity."

    How is it getting this user name value?

    Is there anyway I can set it with another value?

    By using wsHttpBinding and the Message attribute, does this mean it is using the SOAP message security? (The body is encrypted and signed.)

    Thanks.

    Friday, February 21, 2014 2:46 PM
  • User-417640953 posted

    How is it getting this user name value?

    Is there anyway I can set it with another value?

    By using wsHttpBinding and the Message attribute, does this mean it is using the SOAP message security? (The body is encrypted and signed.)

    Hi gloria10,

    Thanks for your back.

    ServiceSecurityContext.Current.PrimaryIdentity, the primary identity is derived from the credentials used to authenticate the user.

    As for the wsHttpBinding "Message" model the default clientCredentialType is "Windows". So you will get the "User Name for Windows Authentication".

    If you want to get another value, please try to set the clientCredentialType as other type. Like "None", "UserName", "Certificate Issued-Token".

    <wsHttpBinding>
       <binding name="MyWsBinding1">
          <security mode="Message">
    	<message clientCredentialType="Certificate" /> 
          </security>
       </binding>
    </wsHttpBinding>

    For more information, please refer to below link.

    http://msdn.microsoft.com/en-us/library/ms731058(v=vs.110).aspx

    As for your second question, "By using wsHttpBinding and the Message attribute, does this mean it is using the SOAP message security", please check below

    thread for a answer.

    http://stackoverflow.com/questions/8076496/wshttpbinding-message-security

    Thanks.

    Best Regards!

    Sunday, February 23, 2014 12:05 AM
  • User201331998 posted

    I tried using the 'UserName' option and I get the error of 'The service certificate is not provide. Specify a service certificate in ServiceCredentials'.

    Is there any way that I can use the User Name Password Validator without using a certificate?

    I was thinking I setting the ClientCredentials.UserName and Password, add the UserNamePasswordValidator class to the service.  Looking to the documentation, it describes using a service certificate at the service level.  I have 2 endpoints, one secure and one not secure.  If I provide a certificate at the service level, will both endpoints need to use this certificate?

    Is there any way I can using validation without a service certificate?

    Monday, February 24, 2014 12:10 PM
  • User-417640953 posted

    Hi gloria10,

    Thanks for your back.

    If you want to use the wsHttpBinding Message security model and clientCredentialType as "UserName".

    The client side should provide username and password like below.

    // Create the binding.
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.Message;
    binding.Security.Message.ClientCredentialType =MessageCredentialType.UserName;
    
    // Create the URI for the endpoint.
    Uri httpUri = new Uri("http://localhost/Calculator");
    
    // Create the service host.
    ServiceHost myServiceHost =
        new ServiceHost(typeof(Calculator), httpUri);
    myServiceHost.AddServiceEndpoint(typeof(ICalculator), binding, "");
    
    // Specify a certificate to authenticate the service.
    myServiceHost.Credentials.ServiceCertificate.
        SetCertificate(StoreLocation.LocalMachine,
        StoreName.My,
        X509FindType.FindBySubjectName,
        "Contoso.com");
    
    myServiceHost.Open();
    Console.WriteLine("Listening...");
    Console.ReadLine();
    
    // Close the service. 
    myServiceHost.Close();
    

    For the whole example, please check below article carefully. Thanks.

    http://msdn.microsoft.com/en-us/library/ms731058(v=vs.110).aspx

    Regards!

    Monday, February 24, 2014 8:51 PM
  • User201331998 posted

    I was finally able to figure out how to implement Message Security using a custom user name authentication.  It needed a service certificate.  To add one to your local machine to test your service is not trivial.  This is the website with the instructions:

    http://msdn.microsoft.com/en-us/library/ff647171.aspx

    Thanks for all of your help!

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 26, 2014 1:55 PM