• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 382
  • Last Modified:

WCF Security

I hate to post long messages on a disucssion forum but I dont think I have an option here.

I have a simple "Hello World" WCF service and a simple winform client. Everything is built using VS 2010 and .Net 4.0 and all applications run locally on my WinXP desktop.

My experiment is based on this link.
http://blogs.msdn.com/b/pedram/archive/2007/10/05/wcf-authentication-custom-username-and-password-validator.aspx

So I was trying to build this WCF service using custom authentication and self signed certificate.

The service app.config file reads.
...
<system.serviceModel>
      <diagnostics>
        <messageLogging logEntireMessage="true" logMalformedMessages="false" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" maxMessagesToLog="3000" maxSizeOfMessageToLog="2000"/>
      </diagnostics>
      <behaviors>
        <serviceBehaviors>
          <behavior name="CreditCardServiceBehavior">
            <serviceMetadata httpGetEnabled="true"/>
          </behavior>
          <behavior name="CustomValidator">
            <serviceCredentials>
              <serviceCertificate findValue="CIS525" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CreditcardValidationService.CIS525Authenticator, CreditcardValidationService"/>
            </serviceCredentials>
            <serviceMetadata/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
        <services>
            <service behaviorConfiguration="CustomValidator" name="CreditcardValidationService.ValidateCreditCardService">
                <endpoint address="base" binding="wsHttpBinding" bindingConfiguration=""
                    contract="CreditcardValidationService.ICreditcardValidationService" />
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8080/CreditCardValidationService" />
                    </baseAddresses>
                </host>
            </service>
        </services>
      <bindings>
        <wsHttpBinding>
          <binding name="httpWithMessageSecurity">
            <security mode="None" >
              <message clientCredentialType="UserName"/>
            </security>
          </binding>
        </wsHttpBinding>
      </bindings>
        <client/>
    </system.serviceModel>
....


The client app.config reads:
    <system.serviceModel>
        <diagnostics>
            <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"/>
        </diagnostics>
        <bindings>
          <wsHttpBinding>
                <binding name="wsHttpBinding_ICreditcardValidationService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                     <security mode="Message" >
                    <message clientCredentialType="UserName"/>
                  </security>
                </binding>
            </wsHttpBinding>
         </bindings>
        <client>
          <endpoint address="http://localhost:8080/CreditCardValidationService/base" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_ICreditcardValidationService" contract="ValidateCreditCardServiceReference.ICreditcardValidationService" name="wsHttpBinding_ICreditcardValidationService">
            <identity>
              <dns value="CIS525"/>
            </identity>
          </endpoint>
        </client>
    </system.serviceModel>

I installed a self signed certificate in Trusted People store and also in trusted root certification authorities. Windows recognizes my certificate as valid when I open the certificate file.

My custom validator is like this.

namespace CreditcardValidationService
{
    public class CIS525Authenticator : UserNamePasswordValidator
    {

    public override void Validate(string userName, string password)

    {
        //check for null user name and password
        if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))

            throw new SecurityTokenException("Username and password required");
    }

}

}

When I call my service from the client application, I get this error:
Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint.

I dont know what I am doing wrong. Please help.

0
shekhar_shashi
Asked:
shekhar_shashi
1 Solution
 
shekhar_shashiAuthor Commented:
There were a couple of issues with the configuration and after fixing those, the code runs fine.

1. I did not have access to the certificate's private key and so the certification could not be used. I granted acesss to myself on the keys by using winhttpcertcfg tool.
2. Service's behavior configuration was blank.

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now