-1

I've been trying to figure this out for a couple of days. I know that I'm close but can't quite figure out what I'm missing.

  • The service is in a website hosted on IIS
  • Basic authentication is enabled for the site, and all others including anonymous authentication is disabled.
  • I have created a self signed certificate and set up a https binding
  • I have overridden the Validate method of the UsernamePasswordValidator but when I attach a break point it isn't reached. So my problem is likely something to do with this.
  • When I attempt to access my service method at https://localhost/Services/JobSiteService.svc/rest/get I am continually prompted for username and password as i receive a 401 unauthorized error.

Can anyone see what I'm doing wrong?

Appropriate code below:

Web.Config

  <system.serviceModel>
<bindings>
  <webHttpBinding>
    <binding name="webHttpTransportSecurity">
      <security mode="Transport">
        <transport clientCredentialType="Basic"  />
      </security>
    </binding>
  </webHttpBinding>
</bindings>

<services>
  <service name="Validity.WebService.JobSiteService" behaviorConfiguration="SecureRestBehavior">
    <endpoint address="rest"  binding="webHttpBinding" behaviorConfiguration="RESTBehavior" bindingConfiguration="webHttpTransportSecurity" contract="Validity.WebService.Contracts.IJobSiteService"  />
    <endpoint address="meta" binding="mexHttpsBinding" contract="IMetadataExchange" />
  </service>
</services>

<behaviors>
  <serviceBehaviors>
    <behavior name="SecureRestBehavior">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>

      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom"  customUserNamePasswordValidatorType="Validity.WebService.IdentityValidator, Validity.WebService" />
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>

  <endpointBehaviors>
    <behavior name="RESTBehavior" >
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

<protocolMapping>
  <add binding="webHttpBinding" scheme="https" />
</protocolMapping>

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

Service Contract:

    [ServiceContract]
public interface IJobSiteService
{
    [OperationContract]
    [WebInvoke(Method="GET", ResponseFormat=WebMessageFormat.Json)]
    List<JobSite> Get();
}

Custom Validator (it's in the namespace "Validity.WebService" but the code formatting broke when I included it.):

        public override void Validate(string userName, string password)
    {
        using (var context = new ValidityContext())
        {

            using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context)))
            {
                var user = userManager.Find(userName, password);
                if (user == null)
                {
                    var msg = String.Format("Unknown Username {0} or incorrect password {1}", userName, password);
                    throw new FaultException(msg);//the client actually will receive MessageSecurityException. But if I throw MessageSecurityException, the runtime will give FaultException to client without clear message.
                }
                else
                {

                    SessionOperationContext.Current.Items["CurrentUser"] = user;
                }
            }
        }
    }

Any help with this would be greatly appreciated.

ErnieStings
  • 6,333
  • 19
  • 47
  • 54
  • You have only shown the server side information. It is the client that must provide the Authorization header to IIS so focus there first. – Crowcoder Jul 10 '16 at 17:12
  • Thanks Crowcoder, It looks like a problem was with IIS validating my auth header against windows credentials rather than using my custom validate method. – ErnieStings Jul 10 '16 at 17:23

1 Answers1

0

Finally figured this out.

The solution was to disable basic authentication on the IIS server and override the CheckAccessCore method of the ServiceAuthorizationManager to validate the user.

ErnieStings
  • 6,333
  • 19
  • 47
  • 54
  • yes it works ,but i have another question do you implement an authorization in wcf webhttpbinding ?https://stackoverflow.com/questions/45770217/my-customauthorizationpolicy-evaluate-method-never-fires – Ehsan Akbar Aug 22 '17 at 06:11
  • I noticed this same thing. I didn't have to do this on my local machine but when deploying to IIS on a server I was required to disable basic authentication in order to fully use my override of CheckAccessCore. Otherwise I would constantly get invalid credentials. – enr4ged May 17 '18 at 20:40