troubleshooting Question

wcf service with usename password validation

Avatar of patd1
patd1Flag for United States of America asked on
.NET ProgrammingWCF
20 Comments3 Solutions2375 ViewsLast Modified:
I have created a wcf service and want to do username password validation in this service. So I created a custom UserNamePassValidator  as shown in the code.

class UserNamePassValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (userName == null || password == null)
            {
                throw new ArgumentNullException();
            }

            if (!(userName == "MyUser" && password == "MyPass"))
            {
                throw new FaultException("Incorrect Username or Password");
            }
        }

The wcf configuration is as follows:
<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpBinding" allowCookies="true"
          maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client />
    <services>
      <service behaviorConfiguration="MyWCF_Behavior" name="MyWCF_ReportService.MyWCF_ReportService">
        <endpoint address="wsHttpBinding" binding="wsHttpBinding" bindingConfiguration=""
          name="wsHttpBinding" bindingName="wsHttpBinding" contract="MyWCF_ReportService.IMyWCF_ReportService" />
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          name="mex" bindingName="mex" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/MyWCF_ReportService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyWCF_Behavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine"
              storeName="My" x509FindType="FindBySubjectName" />
            <userNameAuthentication userNamePasswordValidationMode="Custom"
              customUserNamePasswordValidatorType="MyWCF_ReportService.UserNamePassValidator, MyWCF_ReportService" />
          </serviceCredentials>
          <serviceDebug />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

The service is hosted on IIS.

I also created a certificate and installed it.
I created a desktop client that consumes the wcf service to generate report. code as follows:
 private void button1_Click(object sender, EventArgs e)
        {
            Dictionary<string, string> d = new Dictionary<string, string>()
	        {
	            {"MemberID", "MX12345"}
	        };
            // Method 1: Create the client using the configuration file

            MyWCF_ReportServiceReference.MyWCF_ReportServiceClient c = new MyWCF_ReportServiceReference.MyWCF_ReportServiceClient("wsHttpBinding");
            c.ClientCredentials.UserName.UserName = "ussr";
            c.ClientCredentials.UserName.Password = "pswd";
            c.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
            try
            {
                Byte[] ReportArray = c.GenerateSSRSReport("/DataMgt/Sample1", d);
                SaveReport(ReportArray);
            }
            catch (FaultException<MyFaultException> ee) { textBox2.Text = ee.Detail.Reason; }
            catch (System.InvalidOperationException ie) { textBox2.Text = ie.Message; }
            catch (TimeoutException te) { textBox2.Text = te.Message; }
            catch (FaultException fEx) { textBox2.Text = fEx.Message; }
            catch (CommunicationException ce) { textBox2.Text = ce.Message; }
            finally
            {
                c.Close();
            }
        }

 public static void SaveReport(byte[] reportBytes)
        {
...... //code to save file on server
}

As you can see the UserNamePassValidator  class in the WCF service has the user name password different from what is passed in the client code. But, it still generates the report and saves it correctly.  I was expecting it to throw new FaultException("Incorrect Username or Password") but, that is not happening. Why?

Thanks for your help.
ASKER CERTIFIED SOLUTION
Aaron Jabamani
Technical Architect

Our community of experts have been thoroughly vetted for their expertise and industry experience.

Join our community to see this answer!
Unlock 3 Answers and 20 Comments.
Start Free Trial
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 3 Answers and 20 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros