locked
Simple WCF with Username/Password Authentication RRS feed

  • Question

  • User-1959374973 posted

    I have created a simple WCF web service and accompanying web application to host the service.

    I'm able to deploy the web application to a test server (that is available to the public).  What I need to do now is add username/password authentication to the web service.  I do not want Windows Authentication and would like to avoid having to create and manage certificates.  How can I do this?

    Below is my unaltered web config:

    <?xml version="1.0"?>
    <configuration>

      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <!--
            To browse web app root directory during debugging, set the value below to true.
            Set to false before deployment to avoid disclosing web app folder information.
          -->
        <directoryBrowse enabled="true"/>
      </system.webServer>

    </configuration>

    Tuesday, August 1, 2017 1:56 PM

Answers

All replies

  • Tuesday, August 1, 2017 2:33 PM
  • User-1959374973 posted

    I have created a custom UserNamePasswordValidator:

    using System;
    using System.IdentityModel.Selectors;
    using System.IdentityModel.Tokens;
    
    namespace Company.Group.ServiceLib
    {
        public class ServiceAuthenticator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                // Validate arguments
                if (String.IsNullOrEmpty(userName))
                {
                    throw new ArgumentNullException("userName");
                }
    
                if (String.IsNullOrEmpty(password))
                {
                    throw new ArgumentNullException("password");
                }
    
                // Check the user name and password
                if (userName != "test" || password != "test")
                {
                    throw new SecurityTokenException("Unknown username or password.");
                }
            }
        }
    }

    And I've modified my web.config:

    <?xml version="1.0"?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        
        <behaviors>
          <serviceBehaviors>
            <behavior name="DefaultBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Company.Group.ServiceLib.ServiceAuthenticator, Company.Group.ServiceLib" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <bindings>
          <basicHttpBinding>
            <binding name="DefaultBinding">
              <security mode="TransportCredentialOnly">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        
        <services>
          <service name="Company.Group.ServiceLib.HelloService" behaviorConfiguration="DefaultBehavior">
            <endpoint address="/HelloServics.svc" binding="basicHttpBinding" bindingConfiguration="DefaultBinding" name="DefaultEndpoint" contract="Company.Group.ServiceLib.IHelloService" />
          </service>
        </services>
        
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    
    </configuration>
    

    It runs fine locally but it does not use the custom validator.  I deployed the web app to our test server and it gives me a 500 error.

    Tuesday, August 1, 2017 5:16 PM
  • User475983607 posted

    Working example...

    WCF Config

    <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="DefaultBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfDemoService.ServiceAuthenticator, WcfDemoService" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        
        <bindings>
          <basicHttpBinding>
            <binding name="DefaultBinding">
              <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
    
        <services>
          <service name="WcfDemoService.Service1" behaviorConfiguration="DefaultBehavior" >
            <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
            <endpoint address="/Service1.svc" binding="basicHttpBinding" bindingConfiguration="DefaultBinding" name="DefaultEndpoint" contract="WcfDemoService.IService1" />
          </service>
        </services>
        
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>  
        
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>

    Username Validator

    namespace WcfDemoService
    {
        public class ServiceAuthenticator : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                // Validate arguments
                if (String.IsNullOrEmpty(userName))
                {
                    throw new ArgumentNullException("userName");
                }
    
                if (String.IsNullOrEmpty(password))
                {
                    throw new ArgumentNullException("password");
                }
    
                // Check the user name and password
                if (userName != "test" || password != "test")
                {
                    throw new SecurityTokenException("Unknown username or password.");
                }
            }
        }
    }

    I set IIS Express to run the service under HTTPS 

    Client console where the SSL validation is disabled since I'm using a self cert.

            static void Main(string[] args)
            {
                System.Net.ServicePointManager.ServerCertificateValidationCallback =
                    delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                    { return true; };
    
                Service1Client client = new Service1Client();
                client.ClientCredentials.UserName.UserName = "test";
                client.ClientCredentials.UserName.Password = "test";
                string result = client.GetData(5);
    
                Console.WriteLine(result);
            }

    Console config

        <system.serviceModel>
            <bindings>
                <basicHttpBinding>
                    <binding name="DefaultEndpoint">
                        <security mode="TransportWithMessageCredential" />
                    </binding>
                </basicHttpBinding>
            </bindings>
            <client>
                <endpoint address="https://localhost:44372/Service1.svc/Service1.svc"
                    binding="basicHttpBinding" bindingConfiguration="DefaultEndpoint"
                    contract="ServiceReference1.IService1" name="DefaultEndpoint" />
            </client>
        </system.serviceModel>

    Tuesday, August 1, 2017 6:40 PM
  • User-1959374973 posted

    I have the following line:

    <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />

    In my app.config for the ServiceLib not in the web.config of my Services app.

    Tuesday, August 1, 2017 7:54 PM
  • User-1959374973 posted

    I also enabled my web app project for SSL.  It gives me https://localhost:44300 for the URL.  I changed the Project URL to be https://localhost:44300/ in the project properties.  But it gives me an error when I try to debug the service.

    Error: Cannot obtain Metadata from https://localhost:44300/HelloService.svc

    Tuesday, August 1, 2017 8:03 PM
  • User1168443798 posted

    Hi esr124,

    >> In my app.config for the ServiceLib not in the web.config of my Services app.

    You need to specify the configuration in the web.config.

    >> Cannot obtain Metadata from https://localhost:44300/HelloService.svc

    If it did not work after moving the configuration from app.cofnig to web.config, I suggest you change the endpoint like below:

    <endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" />

    Best Regards,

    Edward

    Wednesday, August 2, 2017 3:29 AM
  • User475983607 posted

    In my app.config for the ServiceLib not in the web.config of my Services app.

    You created a WCF service library not a Service Application?  That was not mentioned at all in the problem description!

    You'll need to move the configuration from the app.config to the configuration file of your hosting environment. If the WCF service is hosted in IIS , then move the configuration from the app.config to the web.config.

    Wednesday, August 2, 2017 10:39 AM
  • User-1959374973 posted

    I moved the endpoint for the metadata from my app.config to the web.config so that I now have this in my web.config:

        <services>
          <service name="Company.Group.ServiceLib.HelloService" behaviorConfiguration="DefaultBehavior">
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <endpoint address="/HelloServics.svc" binding="basicHttpBinding" bindingConfiguration="DefaultBinding" name="DefaultEndpoint" contract="Company.Group.ServiceLib.IHelloService" />
          </service>
        </services>

    When I run the web application locally it launches the WCF Test Client and gives the following error:

    Error: Cannot obtain Metadata from https://localhost:44301/HelloService.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.  For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error    URI: https://localhost:44301/HelloService.svc    Metadata contains a reference that cannot be resolved: 'https://localhost:44301/HelloService.svc'.    Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost:44301'.    The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.    The remote certificate is invalid according to the validation procedure.HTTP GET Error    URI: https://localhost:44301/HelloService.svc    There was an error downloading 'https://localhost:44301/HelloService.svc'.    The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.    The remote certificate is invalid according to the validation procedure.

    Thursday, August 3, 2017 3:23 PM
  • User-1959374973 posted

    I created a service library and then a service application with a HelloService.svc file that references the service in the service library.

    HelloService.svc file:

    <%@ ServiceHost Language="C#" Debug="true" Service="Company.Group.ServiceLib.HelloService" %>

    What all needs moved from the app.config to the web.config?

    app.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" />
      </system.web>
      <!-- When deploying the service library project, the content of the config file must be added to the host's 
      app.config file. System.Configuration does not support config files for libraries. -->
      <system.serviceModel>
        <services>
          <service name="Psu.Ecss.ServiceLib.HelloService">
            <endpoint address="" binding="basicHttpBinding" contract="Company.Group.ServiceLib.IHelloService">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:8733/Design_Time_Addresses/ServiceLib/HelloService/" />
              </baseAddresses>
            </host>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, 
              set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
              <!-- To receive exception details in faults for debugging purposes, 
              set the value below to true.  Set to false before deployment 
              to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    
    </configuration>
    

    web.config

    <?xml version="1.0"?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        
        <behaviors>
          <serviceBehaviors>
            <behavior name="DefaultBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Company.Group.ServiceLib.ServiceAuthenticator, Company.Group.ServiceLib" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <bindings>
          <basicHttpBinding>
            <binding name="DefaultBinding">
              <security mode="TransportCredentialOnly">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        
        <services>
          <service name="Company.Group.ServiceLib.HelloService" behaviorConfiguration="DefaultBehavior">
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <endpoint address="/HelloServics.svc" binding="basicHttpBinding" bindingConfiguration="DefaultBinding" name="DefaultEndpoint" contract="Company.Group.ServiceLib.IHelloService" />
          </service>
        </services>
        
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    
    </configuration>
    

    Thursday, August 3, 2017 3:29 PM
  • User475983607 posted

    I created a service library and then a service application with a HelloService.svc file that references the service in the service library.

    You don't need a WCF Library if you created a WCF application.  Use one or the other not both.

    Thursday, August 3, 2017 3:33 PM
  • User-1959374973 posted

    mgebhard

    You don't need a WCF Library if you created a WCF application.  Use one or the other not both.

    I created a new WCF Service Application (no library, just the application).  I added the ServiceAuthenticator.cs file and adjusted the web.config accordingly.

    I ran the application and the WCF Test Client worked fine.

    I changed the project to allow SSL (SSL Enabled = True) and was given a SSL URL of https://localhost:44302.

    I then changed the Project Url to match that SSL URL in the project properties.

    I get the following error:

    Error: Cannot obtain Metadata from https://localhost:44302/Service.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.  For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error    URI: https://localhost:44302/Service.svc    Metadata contains a reference that cannot be resolved: 'https://localhost:44302/Service.svc'.    Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost:44302'.    The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.    The remote certificate is invalid according to the validation procedure.HTTP GET Error    URI: https://localhost:44302/Service.svc    There was an error downloading 'https://localhost:44302/Service.svc'.    The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.    The remote certificate is invalid according to the validation procedure.

    Below is my web.config file:

    <?xml version="1.0"?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior">
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <serviceCredentials>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService.ServiceAuthenticator, WcfService" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <basicHttpBinding>
            <binding name="ServiceBinding">
              <security mode="TransportCredentialOnly">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <services>
          <service behaviorConfiguration="ServiceBehavior" name="WcfService.Service" >
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <endpoint address="/Service.svc" binding="basicHttpBinding" bindingConfiguration="ServiceBinding" name="ServiceEndpoint" contract="WcfService.IService" />
          </service>
        </services>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    
    </configuration>
    

    Thursday, August 3, 2017 5:31 PM
  • User-1959374973 posted

    Even though I receive that error about the metadata.  IIS Express still starts and has both the http and https addresses listed under WcfService.

    From my WCF test console application, I can add a reference to the https version of the service to my application and execute the GetData() from the application successfully.  It will return the result from the function, but it shouldn't, because I don't give it any username/password.

    Here is the code from my console app:

    using System;
    using System.Net;
    
    namespace ConsumeWcfServiceTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Starting application");
    
                Console.WriteLine("Creating web service object");
    
                Service.ServiceClient client = new Service.ServiceClient();
    
                string results = client.GetData(5);
    
                Console.WriteLine("Web service results: {0}", results);
    
                Console.WriteLine("Ending applicaiton");
    
                Console.WriteLine();
                Console.Write("Press any key to exit");
                Console.ReadKey(true);
            }
        }
    }
    

    Thursday, August 3, 2017 5:41 PM
  • User475983607 posted

    I'm not sure what else I can do for you.  I provided a working example... you need to compare your configuration with the working example.

    ie.

        <bindings>
          <basicHttpBinding>
            <binding name="DefaultBinding">
              <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>

    Thursday, August 3, 2017 6:28 PM
  • User-1959374973 posted

    Here is a link to the simple project that I have:

    https://www.dropbox.com/s/cqbaphlj2tk18br/WcfService.7z?dl=0

    This project will run fine locally under http.  If I enable SSL and change the project URL to the SSL URL and try to run it then I get the metadata error message.

    Thursday, August 3, 2017 6:56 PM
  • User475983607 posted

    You need to turn off the SSL verification as suggested above as the cert is not from an authority.

     System.Net.ServicePointManager.ServerCertificateValidationCallback =
                    delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                    { return true; };

    Thursday, August 3, 2017 8:06 PM
  • User-1959374973 posted

    You need to turn off the SSL verification as suggested above as the cert is not from an authority.

     System.Net.ServicePointManager.ServerCertificateValidationCallback =
                    delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                    { return true; };

    Where exactly does that code go?

    Thursday, August 3, 2017 8:09 PM
  • User-1959374973 posted

    You need to turn off the SSL verification as suggested above as the cert is not from an authority.

     System.Net.ServicePointManager.ServerCertificateValidationCallback =
                    delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                    { return true; };

    I seem to remember this code going in client application that will be calling the service.

    I'm still trying to get the service to work with a username and password on https.

    Thursday, August 3, 2017 8:14 PM
  • User-1959374973 posted

    Not sure if I should just start a new thread and explain myself clearer.

    What I need to do is create a web service that takes a username and password and deploy that to a server where it will be accessed over https.

    I've run into several issues:

    First the username/password validator is never called when running the service locally.  Apparently this is because the validator is only used when it runs over https.

    I've tried enabling SSL within the project and that causes an error.  Deploying the app to localhost and enabling SSL on the webapp kind of works.  I'm able to browse to the service through my web browser, but I can't call it from an app or get SoapUI to find it.  The WSDL is showing a URL with HTTP not HTTPS.

    Friday, August 4, 2017 2:49 AM
  • User475983607 posted

    esr124

    Not sure if I should just start a new thread and explain myself clearer.

    What I need to do is create a web service that takes a username and password and deploy that to a server where it will be accessed over https.

    No, you request is very clear and I provided a working example of how to do this.  However, for some reason you are continue to use TransportCredentialOnly.

    esr124

    First the username/password validator is never called when running the service locally.  Apparently this is because the validator is only used when it runs over https.

    This is not totally of correct.  You should not be a able to call the server if the request is not over HTTPS using the configuration suggested above.  The service should throw the exception below.

    Unhandled Exception: System.ArgumentException: The provided URI scheme 'http' is invalid; expected 'https'.

    esr124

    I've tried enabling SSL within the project and that causes an error.  Deploying the app to localhost and enabling SSL on the webapp kind of works.  I'm able to browse to the service through my web browser, but I can't call it from an app or get SoapUI to find it.  The WSDL is showing a URL with HTTP not HTTPS.

    Have you tried using the working source code?  Are you still wrapping a WCF library in a WCF application?  Have you changed the behavior to use TransportWithMessageCredential?  Keep in mind that TransportCredentialOnly is used when the channel is secure outside WCF.  Using TransportCredentialOnly requires a different validator.  Perhaps you wan to send the base-64 encoded credentials (basic authentication) in the header?

    Friday, August 4, 2017 10:41 AM
  • User-1959374973 posted

    Have you tried using the working source code?  Are you still wrapping a WCF library in a WCF application?  Have you changed the behavior to use TransportWithMessageCredential?  Keep in mind that TransportCredentialOnly is used when the credentials are passed in the HTTP header not the message as the example shows.  Using TransportCredentialOnly requires a different validator.  Is that what you want?  To send the base-64 encoded credentials (basic authentication) in the header?

    So I created a new project without a library that way there is not an app.config and a web.config, there is just a web.config now.

    The service will be hosted on a server with HTTPS.  Which behavior should be used for username/password authentication?  TransportWithMessageCredential?

    And what binding should be used?  basicHttpBinding or wsHttpBinding?

    Friday, August 4, 2017 1:02 PM
  • User475983607 posted

    The service will be hosted on a server with HTTPS.  Which behavior should be used for username/password authentication?  TransportWithMessageCredential?

    Yes, then the custom validator will work as documented here.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-a-custom-user-name-and-password-validator

    And what binding should be used?  basicHttpBinding or wsHttpBinding?

    Use wsHttpBinding if you want or need the additional features.  Keep in mind, wsHttpBinding requires a certificate which goes against your original requirement. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, August 4, 2017 1:47 PM
  • User-1959374973 posted

    I think I finally got it working.

    I changed the security mode to TransportWithMessageCredential.

    I enabled SSL for the project.  That gave me an SSL URL of https://localhost:44375/.

    I changed the Project Url to https://localhost:44375/.

    I ran the application which launched the WCF Test Client.  This showed the https URL for the service.

    I switched over to my WcfServiceTest console application project.  I added a service reference with the URL https://localhost:44375/Service.svc.

    I ran my WcfServiceTest application and with the credentials part commented out it failed.  I uncommented the setting of the credentials and it worked.  The Validate() function was called.  I had set a breakpoint in function.  Trying a username and password that were not correct also caused an exception.

    The only thing that did not work was when I tried testing with SoapUI.  I got an error: Error loading WSDL

    Friday, August 4, 2017 2:43 PM
  • User-1959374973 posted

    I figured out the issue with loading the WSDL.  I needed to use https://localhost:44375/Service.svc?wsdl.

    The wsdl loaded but the call to GetData() failed with the following error:

    An error occurred when verifying security for the message.

    I provided the username and password in the properties for the request.

    Friday, August 4, 2017 3:01 PM
  • User475983607 posted

    esr124

    An error occurred when verifying security for the message.

    I provided the username and password in the properties for the request.

    Again, the provided sample works... compare your work to the sample code.  Otherwise post your source code if you need help finding the bug.

    Friday, August 4, 2017 3:35 PM
  • User-1959374973 posted

    Here is a link to the code that works locally with https but gives an error when trying SoapUI:

    https://www.dropbox.com/s/k02k5gk29kfwi9x/WcfService%202.7z?dl=0

    Friday, August 4, 2017 5:28 PM
  • User475983607 posted

    Here is a link to the code that works locally with https but gives an error when trying SoapUI:

    If I understand correctly, the WCF service and .NET client are working.  The new issue is, you are having difficulty formatting the SoapUI message???

    If you are that concerned, use a proxy like Fiddler to capture the SOAP message and compare that to the SoapUI message.  Or enable tracing.

    Frankly, if the WCF service and .NET client are working then the problem is solved.

    Friday, August 4, 2017 7:16 PM
  • User1120430333 posted

    The only thing that did not work was when I tried testing with SoapUI.  I got an error: Error loading WSDL

    You need to kick that junk to the curb and move on. If it worked with a .NET client consuming the WCF service, then what is the point of the SoapJunk? 

    Friday, August 4, 2017 7:30 PM
  • User-1959374973 posted

    Frankly, if the WCF service and .NET client are working then the problem is solved.

    My only concern is that this service will be consumed by a 3rd party application.  I figured if it works with SoapUI, it should work with anything.

    Friday, August 4, 2017 9:07 PM
  • User-1959374973 posted

    It works when I run the service through Visual Studio 2015 with https and then run my console application.

    I deployed the service application to my local instance of IIS and when I run my console application it throws an error and says:

    Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'.

    I followed the instructions on the following website before I deployed my app so that localhost would have https:

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-an-iis-hosted-wcf-service-with-ssl

    Friday, August 4, 2017 9:14 PM
  • User1168443798 posted

    Hi esr124,

    >> The only thing that did not work was when I tried testing with SoapUI.  I got an error: Error loading WSDL

    Did it work with SoapUI under VS 2015? If not, since it work with console application, but failed with SoapUI, I suggest you go to SoapUI support for help, they are more familiar with SoapUI.

    >> Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'.

    After you deploy the service to IIS, have you recreated the client code in console application? Have you missed below code in the new console application?

    System.Net.ServicePointManager.ServerCertificateValidationCallback +=
        (se, cert, chain, sslerror) =>
            {
                return true;
            };

    Best Regards,

    Edward

    Monday, August 7, 2017 2:10 AM
  • User-1959374973 posted

    Hi esr124,

    >> The only thing that did not work was when I tried testing with SoapUI.  I got an error: Error loading WSDL

    Did it work with SoapUI under VS 2015? If not, since it work with console application, but failed with SoapUI, I suggest you go to SoapUI support for help, they are more familiar with SoapUI.

    I was able to get the WSDL to load but when I attempt to make the call with SoapUI it fails with the error message:

    An error occurred when verifying security for the message.

    Tuesday, August 8, 2017 1:45 PM
  • User-1959374973 posted

    >> Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'.

    After you deploy the service to IIS, have you recreated the client code in console application? Have you missed below code in the new console application?

    System.Net.ServicePointManager.ServerCertificateValidationCallback +=
        (se, cert, chain, sslerror) =>
            {
                return true;
            };

    Adding the above code to the beginning of my C# test program makes it work.

    So it looks like SoapUI is the only thing I can't get working.

    Tuesday, August 8, 2017 1:52 PM
  • User475983607 posted

    esr124

    I was able to get the WSDL to load but when I attempt to make the call with SoapUI it fails with the error message:

    An error occurred when verifying security for the message.

    You are not formatting message security correctly in SoapUI or there is a security issue due to using  a self-sighed certificate.  Refer to SoapUI support for configuration information. 

    You might try the following.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-temporary-certificates-for-use-during-development

    Tuesday, August 8, 2017 1:55 PM
  • User-1959374973 posted

    I've deployed my web service to my server that has a proper SSL certificate and is HTTPS.

    However, when trying to access my service URL https://servername/Services/Service.svc I get a 404 error.

    If I try accessing the svc page from the server i get 404.3 The page you are requesting cannot be served because of the extension configuration.

    This is strange because I was able to deploy wcf services to the server before and access them just fine.

    Could this be because of the security mode being TransportWithMessageCredential?  The other web services that I deployed and could access were either Message or TransportCredentialOnly.

    Tuesday, August 8, 2017 6:41 PM
  • User-1959374973 posted

    I fixed this by running the following command:

    aspnet_regiis.exe -iru

    And then restarted IIS.

    I am now able to call my web service that is deployed on my test server (that has SSL and HTTPS) with my C# test client.  Passing the wrong credentials gives an exception and the correct credentials returns me the result.

    However, when trying to test the service with SoapUI 5.3.0 I get the same error when testing it locally:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
       <s:Body>
          <s:Fault>
             <faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
             <faultstring xml:lang="en-US">An error occurred when verifying security for the message.</faultstring>
          </s:Fault>
       </s:Body>
    </s:Envelope>

    Tuesday, August 8, 2017 6:57 PM
  • User475983607 posted

    Could this be because of the security mode being TransportWithMessageCredential? 

    Doubtful...

    The other web services that I deployed and could access were either Message or TransportCredentialOnly.

    For the third or fourth time TransportCredentialOnly will not work with the custom validator and Message requires a certificate on the client.   

    The site is not configured correct.  A 404 means page not found.   IIS has a default site on port 80.  If you are using the "server name" then you need to setup a binding on a different port, purchase a domain name and configure he site accordingly, or drop the service in the default IIS application.

    A 404.3 is a mime type error which is also points to an IIS configuration issue.

    Tuesday, August 8, 2017 7:01 PM
  • User475983607 posted

    Glad to here you figure out the configuration issue. 

    esr124

    However, when trying to test the service with SoapUI 5.3.0 I get the same error when testing it locally:

    And you expected a different behavior?  You are not properly formatting the SoapUI message as stated several times above.  I'm not sure how to help you with this issue as I am not a SoapUI expert and this is not a SoapUI support forum.

    Try perhaps the following found by Google...

    https://stackoverflow.com/questions/13729270/testing-wcf-service-wshttpbinding-with-security-mode-transportwithmessagecreden

    https://www.soapui.org/soapui-projects/ws-security.html

    https://community.smartbear.com/t5/SoapUI-Open-Source/TransportWithMessageCredential-and-Username/td-p/38917

    Tuesday, August 8, 2017 7:06 PM
  • User-1959374973 posted

    Glad to here you figure out the configuration issue.

    Thank you for all the information thus far.  The various security modes and changes to the web.config really had me going in circles.

    I believe I have a much better understanding now.

    I'm going to try using Fiddler to determine the difference between the messages being sent from the C# client and SoapUI.

    Tuesday, August 8, 2017 8:10 PM
  • User-1959374973 posted

    I'm going to try using Fiddler to determine the difference between the messages being sent from the C# client and SoapUI.

    Didn't need to use Fiddler.  Found the following article right :

    https://forums.asp.net/t/2111898.aspx?SoapUI+WCF+An+error+occurred+when+verifying+security+for+the+message+

    I changed the WS-Password Type to PasswordText and it worked!

    Tuesday, August 8, 2017 8:20 PM
  • User1404573039 posted

    Hi esr124,

    I am glad your issue has been resolved, and I suggest you mark the helpful reply as answer to close this thread.

    Regards,

    Tony

    Wednesday, August 9, 2017 2:12 AM