none
An Unsecured or Incorrectly Secured Fault RRS feed

  • Question

  • I have written a WCF service that requires SSL and a Username/Password to be called by the client.  I chose to use a wsHttpBinding with security mode=TransportWithMessageCredential and a custom userNamePasswordValidationMode.  I can generate the proxy and have no errors in the client setting up the UserName and Password credentials, as well as the information in the DataMember passed to the Operation.  However, when I call the Operation, I receive a CommunicationException of "An unsecured or incorrectly secured fault was received from the other party."  The InnerException is "An error occurred when verifying security for this message."  I placed an entry for an EventLog in the beginning of the UserNamePassworValidator Validate method, but that is never reached.  I have also run a trace log and found errors listed in three places.  In Activity - 0, the ServiceModel error is "Message security verification failed.".  In Activity - Listen at 'https://...', the ServiceModel error is "There is a problem with the XML that was received from the network.".  In Activity - Process action'http://schemas.xmlsoap.org/ws/2004/09/Transfer/Get', the ServiceModel error is "There was no channel that could accept the message with action 'http://schemas.xmlsoap.org/ws/2004/09/transfer/Get'."

    From what I have read of this error, it is generally an issue with time being different between the server and the client machines.  However, I have checked them, and they are exactly the same time. 

    The config file I am using has the following set-up.  Is there something else I need to include?

        <services>
          <service behaviorConfiguration="SecurityServiceBehavior" name="UploadService.MyService">
            <host>
              <baseAddresses>
                <add baseAddress="https://Services.MySite.com/UploadService/"/>
              </baseAddresses>
            </host>
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="SecurityBinding" 
                      bindingNamespace="UploadService" name="wsHttpEndpoint"
                      contract="UploadService.IMyService" >
            </endpoint>
            <endpoint address="mex" binding="mexHttpsBinding" 
                      contract="IMetadataExchange" />
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="SecurityServiceBehavior">
              <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
              <serviceDebug includeExceptionDetailInFaults="True" />
              <serviceCredentials>
                <serviceCertificate
                    findValue="services.MySite.com" x509FindType="FindBySubjectName"
                    storeLocation="LocalMachine" storeName="My" />
                <userNameAuthentication
                   userNamePasswordValidationMode="Custom"
                   customUserNamePasswordValidatorType="UploadService.CustomCredentialsValidator, UploadService"/>
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <wsHttpBinding>
            <binding name="SecurityBinding" receiveTimeout="00:05:00" sendTimeout="00:05:00"
                     maxReceivedMessageSize="2147483647" messageEncoding="Mtom">
              <readerQuotas maxStringContentLength="2147483647" maxArrayLength="163840000" />
              <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName" 
                  establishSecurityContext="true"/>
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>

    Also, the UserNamePasswordValidator code is listed below.

     public override void Validate(string userName, string password)
     {
         string strSource = "Upload Service";
         if (!System.Diagnostics.EventLog.SourceExists(strSource))
         {
             System.Diagnostics.EventLog.CreateEventSource(strSource, "Application");
         }
         System.Diagnostics.EventLog.WriteEntry(strSource, "Ready to check credentials");
         if (userName != "test" || password != "test123")
             throw new SecurityTokenValidationException("Invalid credentials");
     }
    

    I set the UserName and Password in the client using

     proxy.ChannelFactory.Credentials.UserName.UserName = "test";
     proxy.ChannelFactory.Credentials.UserName.Password = "test123";
    

    Thanks in advance for your help!


    Christine A. Piffat

    Friday, June 15, 2012 6:54 PM

Answers

  • Hi Christine

    First this service uses mtom. I suggest to temprarly set both service and client to Text encoding instead - much easier to debug.

    Next you may want to establishSecurityContext and negotiateServerCredential to false for the same reason (both are properties of the security/message node).

    We can add them back again later when we figure it out.

    Now, sorry for insisting on this point but it is the only way to sort this out - we must understand what is received by WCF and what error it internally has.

    So try to do this again:

    1. close your wcf service

    2. delete any existing wcf trace or log file

    3. make sure wcf trace AND logging are defined on the server

    http://blogs.msdn.com/b/madhuponduru/archive/2006/05/18/601458.aspx

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

    when you confugure logging make sure to set logMessagesAtTransportLevel and logEntireMessage to true .

    4. now run the serivce and the client - do not watch the service in IE or download its wsdl - I want to log files to be clean

    5. now check in the log file what exactly the client sent (at the transport level log entry, not serive level entry). also check the error (and inner exceptions) in the trace file.

    if you are not sure in any of these steps (or want to share with me the raw log files) feel free to drop ma a mail at yaronn01@gmail.com

    Thanks,
    Yaron


    http://webservices20.blogspot.com/
    WCF Security, Interoperability And Performance Blog

    Tuesday, June 19, 2012 5:13 PM
  • I thought I should write this up here just to make sure that the answer is online.  The problem I had was that when I had had some SSL issues, I included an EventLog entry in my UserNamePasswordValidator to let me know that I had made it that far.  Because the event source has never been created, I was unable to write to the event log as a non-admin.  Of course, my WCF service runs under specific credentials through IIS, so it is not an admin.  If I created this event source under my own credentials, it would probably not be a problem to write entries as my IIS user.  There is more discussion on this on another thread (Security Exception). 

    The biggest help in finding this error is the above message.  Comparing the log files on the client and the server really helped track this down.  I had only looked at the server ones previously.


    Christine A. Piffat

    Tuesday, June 19, 2012 8:47 PM

All replies

  • go back to the trace log and for each of the exceptions above (except the last one about the GET - not interesting) check for its inner exception. it is hidden somewhere in the center of the screen bellow the exception on the right side, but it is there. that is the information you need.

    http://webservices20.blogspot.com/
    WCF Security, Interoperability And Performance Blog

    Friday, June 15, 2012 10:01 PM
  • Thanks!  I hadn't realized that the message would change when you clicked on the treeview.  For the Activity - 0, the message is "The source was not found, but some or all event logs could not be searched.  Inaccessible logs: Security." For the second one, I have "The body of the message cannot be read because it is empty."  I guess that means I am not finding my UserNamePasswordValidator?  For the customUserNamePasswordValidatorType, I should be passing in the following parameter, "Namespace.ClassName, dllName", shouldn't I?  I have my 'codebehind' for the svc file in another dll. 


    Christine A. Piffat

    Friday, June 15, 2012 10:46 PM
  • try to have fiddler on and send your client message to fiddler (http://localhost:8888/). for start we need to verify what is sent, according the 2nd message the body is not sent.

    http://webservices20.blogspot.com/
    WCF Security, Interoperability And Performance Blog

    Friday, June 15, 2012 11:02 PM
  • I installed Fiddler on my computer and have it set to read https.  When I look at the Request Headers, I have the following information. 

    POST /Upload/Upload.svc HTTP/1.1
    Client
       Accept-Encoding: gzip, deflate
    Entity
       Content-Length: 1859
       Content-Type: multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:<guid>+id=1";start-info="application/soap+xml"
    Miscellaneous
       MIME-Version: 1.0
    Transport
       Connection: Keep-Alive
       Expect: 100-continue
       Host: services.mysite.com

    However, when I look at the TextView, it lists the Envelope tag, which includes the correct path for the To tag, a timestamp, and a Username Token with the correct username and password.  The uuid for the header and body are different and are not the same as the one listed after the Envelope tag.  The one listed after the Envelope tag is the same as listed in the Request Headers section.

    Should I try to get Fiddler on the server?  I won't be able to look at https, however. 

    Thanks!


    Christine A. Piffat

    Monday, June 18, 2012 5:12 PM
  • please publish here what is actually sent (fiddler header + body) and what you want to be sent (headers + body).


    http://webservices20.blogspot.com/
    WCF Security, Interoperability And Performance Blog

    Tuesday, June 19, 2012 2:16 PM
  • Okay, I  am extremely frustrated with WCF and I am starting to wonder if there are any non-Microsoft options out there for writing services that actually work correctly.  I have an incredibly easy and common scenario.  I have read hundreds of pages of documentation and watched several hours of videos on how to set this up.  I have had so many ridiculous issues that require making some little change that is rarely or never documented by Microsoft.  When I look on the forums, I keep seeing all the problems I have over and over and over again--many times with no resolution.  (See WCF is Making My Head Hurt for someone else dealing with EXACTLY these issues.)  At the moment, I see absolutely nothing in my set-up that is different from other examples given in videos, books, or Microsoft's own samples.  And yet, it still is not working.  I know there are Microsoft people out there that read these forums, so I am asking them specifically, "What is going on?"  Was there a security patch that broke everything like IE9 did to several features of the WebBrowser in WPF?  Some documentation on these changes would be awesome!!

    Now that I have THAT rant out of the way, I'll describe my problem with the information I have on WCF after using Fiddler.  I put it on my work computer and ran my client application.  As I explained above, the Envelope in the Request sent from my client app contained the UserName and Password.  The content is 1859 (bytes?), which has to include more than the header.  So, somewhere between the Request being sent and my application interpreting that Request, the message is lost.  The custom code on the service that reads the credentials is never run because I have some code in there that writes to the event log, and nothing is written. 

    How do I determine what is wrong from here?  The only idea I had was to move the service onto my local computer and try to use Fiddler to see if that would give me more information.  So, I tried moving it.  Well, now, the service is apparently smart enough to know that my certificate is created from makecert and has decided it can't validate the certificate.  I found some information about using the following under the serviceCredentials: 

    <clientCertificate>
      <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck"/>
    </clientCertificate>
    

    I still had the same error, so I decided to just remove the ssl requirement, use Message security (since that contains the problem most likely), and run as http.  Now, I changed the name of my web.config file to web.config.prod and copied the information (with changes to the security) to a new web.config file.  There is no 'certificate' used anywhere in this new web.config file, but my service is continuing to look for a certificate and gives me an error on that.  I don't even know if Fiddler will give me any more information for all the effort I have put into this, and I have spent an entire day on just this issue alone.  Everywhere I turn on making a change to get this thing running on my computer sends me down another time waster of chasing more obscure errors. (Yes, I fully agree with your blogs "Cryptic WCF Error Messages (part 'x' of N)".)

    At this point, I assume there is either a typo in my config file listed above or there was a patch that broke the way WCF works.  I have spent the last two weeks pouring through one issue after another and have made what appears to anyone at my company as exactly zero progress.  I am so frustrated that I really have to start thinking of alternatives to WCF.  Is there ANYTHING else I can check?  ANY other option to see what is happening to my message body? 

    Sorry for this rant, but in this economy, Microsoft had better understand that they have to have documentation that HELPS their clients be productive.  The complex code in my dll SHOULD have been the hard part--not setting up ROUTINE bindings on the config file.


    Christine A. Piffat

    Tuesday, June 19, 2012 2:22 PM
  • There are two results sent through Fiddler.  The first is an http protocol where the Host is "Tunnel to" and the URL is "services.mysite.com:443" with a body of 0 and a result of 200.  The Request Headers shows the following:

    CONNECT services.mysite.com:443 HTTP/1.1
    Transport
       Connection: Keep-Alive
       Host: services.mysite.com

    The TextView is the following:

    A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
    
    Major Version: 3
    Minor Version: 1
    Random: 4F E0 94 44 E1 50 83 98 EA 16 CF 47 D8 6D 16 95 F9 F9 EC AE 2F 6E A4 9F 20 3C C7 7B 9E 38 7E 91
    SessionID: empty
    Ciphers: 
    	[002F]	TLS_RSA_AES_128_SHA
    	[0035]	TLS_RSA_AES_256_SHA
    	[0005]	SSL_RSA_WITH_RC4_128_SHA
    	[000A]	SSL_RSA_WITH_3DES_EDE_SHA
    	[C013]	TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
    	[C014]	TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
    	[C009]	TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    	[C00A]	TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    	[0032]	TLS_DHE_DSS_WITH_AES_128_SHA
    	[0038]	TLS_DHE_DSS_WITH_AES_256_SHA
    	[0013]	SSL_DHE_DSS_WITH_3DES_EDE_SHA
    	[0004]	SSL_RSA_WITH_RC4_128_MD5
    
    Compression: 
    	[00]	NO_COMPRESSION
    
    Extensions: 
    	renegotiation_info	00
    	server_name	services.mysite.com
    	elliptic_curves	00 04 00 17 00 18
    	ec_point_formats	01 00
    
    

    Under Authorization, it shows "No Proxy-Authorization Header is present. No Authorization Header is present."

    In the Response section, the TextView shows information about our certificate on the server, including the correct thumbprint and issuer. 

    The second result is an https protocol where the host is "services.mysite.com" and the URL is "/Upload/Upload.svc".  The body is listed ast 902 (KB?).  The file I am uploading is 757 KB.  The result is 500.

    The Request Headers has the following listed:

    POST /Upload/Upload.svc HTTP/1.1
    Client 
       Accept-Encoding: gzip, deflate
    Entity
       Content-Length: 1859
       Content-Type: multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:<guid>+id=1";start-info="application/soap+xml"
    Miscellaneous
       MIME-Version: 1.0
    Transport
       Connection: Keep-Alive
       Expect: 100-continue
       Host: services.mysite.com

    The TextView shows the following:

    --uuid:<guid1>+id=1
    Content-ID: <http://tempuri.org/0>
    Content-Transfer-Encoding: 8bit
    Content-Type: application/xop+xml;charset=utf-8;type="application/soap+xml"
    
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
    <a:MessageID>urn:uuid:<guid2></a:MessageID>
    <a:ReplyTo>
    <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">https://services.mysite.com/Upload/Upload.svc</a:To>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <u:Timestamp u:Id="_0">
    <u:Created>2012-06-19T15:01:24.386Z</u:Created>
    <u:Expires>2012-06-19T15:06:24.386Z</u:Expires>
    </u:Timestamp>
    <o:UsernameToken u:Id="uuid-<guid3>-1">
    <o:Username>myuser</o:Username>
    <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password1</o:Password>
    </o:UsernameToken>
    </o:Security>
    </s:Header>
    <s:Body>
    <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
    <t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
    <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
    <t:Entropy>
    <t:BinarySecret u:Id="uuid-<guid4>-1" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce"><44BinaryChars></t:BinarySecret>
    </t:Entropy>
    <t:KeySize>256</t:KeySize>
    </t:RequestSecurityToken>
    </s:Body>
    </s:Envelope>
    --uuid:<guid1>+id=1--
    
     

    The values for guid1 (occurs 2x) are the same as the guid in the Request Headers.  The Binary Secret is 44 characters. 

    Under Authorization, it also shows "No Proxy-Authorization Header is present. No Authorization Header is present."

    I am not sure how to send what the request is supposed to send.  The client proxy has the UserName and Password set, which I assume would be the UserNameToken since they are identical. 

    The body should contain a FileInformation object as described in the DataContract.  There are five fields included in this DataContract, and I have values for all of them, even though one is not required.  The CodeNumber is a text field that I set as "0" for now.  The DeviceName is text set as "Device1".  The TestOrProd is text set as "Production" (we're not live yet anyway).  The FileName is text set to "jellyfish.jpg".  The File is a byte array of 775702 bytes created by using System.IO.File.ReadAllBytes with the jellyfish.jpg under my sample pictures folder. 

    The IUpload interface has several operations, but this is by far the simplest one set up.  I wouldn't think that any other ones would interfere with this one being run correctly.  This operation returns an UploadFileReturn object that has a two DataMembers in its DataContract--Code (int) and Message (string).  Also, the FaultException has its own class, FaultInfo, with two DataMembers--Code (int) and ErrorText (string).  The Response I receive on the 500 result is an untyped fault, however. 

    Thanks for your help!


    Christine A. Piffat

    Tuesday, June 19, 2012 3:57 PM
  • Hi Christine

    First this service uses mtom. I suggest to temprarly set both service and client to Text encoding instead - much easier to debug.

    Next you may want to establishSecurityContext and negotiateServerCredential to false for the same reason (both are properties of the security/message node).

    We can add them back again later when we figure it out.

    Now, sorry for insisting on this point but it is the only way to sort this out - we must understand what is received by WCF and what error it internally has.

    So try to do this again:

    1. close your wcf service

    2. delete any existing wcf trace or log file

    3. make sure wcf trace AND logging are defined on the server

    http://blogs.msdn.com/b/madhuponduru/archive/2006/05/18/601458.aspx

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

    when you confugure logging make sure to set logMessagesAtTransportLevel and logEntireMessage to true .

    4. now run the serivce and the client - do not watch the service in IE or download its wsdl - I want to log files to be clean

    5. now check in the log file what exactly the client sent (at the transport level log entry, not serive level entry). also check the error (and inner exceptions) in the trace file.

    if you are not sure in any of these steps (or want to share with me the raw log files) feel free to drop ma a mail at yaronn01@gmail.com

    Thanks,
    Yaron


    http://webservices20.blogspot.com/
    WCF Security, Interoperability And Performance Blog

    Tuesday, June 19, 2012 5:13 PM
  • I thought I should write this up here just to make sure that the answer is online.  The problem I had was that when I had had some SSL issues, I included an EventLog entry in my UserNamePasswordValidator to let me know that I had made it that far.  Because the event source has never been created, I was unable to write to the event log as a non-admin.  Of course, my WCF service runs under specific credentials through IIS, so it is not an admin.  If I created this event source under my own credentials, it would probably not be a problem to write entries as my IIS user.  There is more discussion on this on another thread (Security Exception). 

    The biggest help in finding this error is the above message.  Comparing the log files on the client and the server really helped track this down.  I had only looked at the server ones previously.


    Christine A. Piffat

    Tuesday, June 19, 2012 8:47 PM