1

I am trying to add UserNamePasswordValidator to 'WCF Rest Service Application' project with visual studio 2010, the problem is.. it never step into UserNamePasswordValidator class, is UserNamePasswordValidator work with Wcf Rest?

Kindly advise..

below is my service class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Security.Principal;


namespace MyService
{
    // Start the service and browse to http://<machine_name>:<port>/Service1/help to view the service's generated help page
    // NOTE: By default, a new instance of the service is created for each call; change the InstanceContextMode to Single if you want
    // a single instance of the service to process all calls.   
    [ServiceContract(Namespace = "MyService")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    // NOTE: If the service is renamed, remember to update the global.asax.cs file
    public class Helo
    {
        [WebGet(UriTemplate = "{name}")]
        public string GetName(string name)
        {
            // TODO: Replace the current implementation to return a collection of SampleItem instances
            return "Hello " + name;
        }

        public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
        {
            // This method validates users. It allows in two users, test1 and test2 
            // with passwords 1tset and 2tset respectively.
            // This code is for illustration purposes only and 
            // MUST NOT be used in a production environment because it is NOT secure.   
            public override void Validate(string userName, string password)
            {
                if (null == userName || null == password)
                {
                    throw new ArgumentNullException();
                }

                if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
                {
                    throw new FaultException("Unknown Username or Incorrect Password");
                }

                throw new FaultException("Unknown Username or Incorrect Password");
            }
        }
    }
}

below is the web.config:

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

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>

  <system.serviceModel>

    <services>
      <service name="MyService.Hello" behaviorConfiguration="HelloServiceBehavior">
        <!-- use base address provided by host, provide one endpoint -->
        <endpoint address="username" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="MyService.Hello"/>
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <!-- Username binding -->
        <binding name="Binding1">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceCredentials>
            <!-- 
            The serviceCredentials behavior allows one to specify a custom validator for username/password combinations.                  
            -->
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyService.Hello+CustomUserNameValidator, MyService"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>


    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <!--<standardEndpoints>
      <webHttpEndpoint>
        --><!-- 
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
            via the attributes on the <standardEndpoint> element below
        --><!--
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>-->
  </system.serviceModel>

</configuration>
user701598
  • 31
  • 1
  • 4

2 Answers2

1

You have to have a webHttpBinding and set the clientCredentialType to basic which will use your derived UserNamePasswordValidator. If you have HTTPS setup then of course change the security mode to Transport:

        <bindings>
        <webHttpBinding>
            <binding name="RestBindingConfiguration">
                <security mode="None">
                    <transport clientCredentialType="Basic"/>
                </security>
            </binding>
        </webHttpBinding>
        </bindings>

On a related side note, FaultExceptions are SOAP only so be aware of that in case you need to throw an exception for the client. Depending on the exceptional case, MessageSecurityException might make sense.

Adam Caviness
  • 3,424
  • 33
  • 37
0

I'm not sure if you are still looking for an answer for this, but in case you are...

Setting up authentication on WCF REST is more than a little tricky. It seems like you modeled your attempt directly from msdn, amirite? I didn't have much luck with it either. You can try to model after this solution, which is a pretty basic example of basic authentication. But my suggestion, because it worked so well for me, is to model your project after WcfRestContrib. Not only is basic authentication already built into the project, but many other features you will eventually discover you want are in there as well. You can enforce authentication for the whole service, or just endpoint by endpoint.

Hope that helps.

Precious Roy
  • 1,086
  • 1
  • 9
  • 19