'Consuming a WCF Service with custom UserNamePasswordValidator

I have a WCF Service running on my windows 2019 server on IIS. The service is to be consumed by a .Net Core library being used within a xamarin enviornment. Everything was working fine, until I wanted to add my custom UserNamePasswordValidator in order to add some security to the service.

My Web.config service section for the server looks like this

<system.serviceModel>
    <services>
        <service name="aircu_web.UpdateService" behaviorConfiguration="debug">
            <endpoint address="" name="wsHttpEndpoint" binding="wsHttpBinding" bindingConfiguration="ServiceBinding" contract="aircu_web.IUpdateService" />
        </service>
    </services>
    <bindings>
        <wsHttpBinding>
            <binding name="ServiceBinding">
                <security mode ="Message">
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="production">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
            <behavior name="debug">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                    <serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="84 d2 c6 d8 85 17 48 30 04 9e 12 e0 bd f4 f3 36 c1 57 b5 6e" storeName="My"/>
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="aircu_web.ApiKeyValidator,aircu_web"/>
                </serviceCredentials>
                
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>

when navigating to https://(mydomain)/UpdateService.svc I can see the "You have created a service" site.

When I add a service reference to my assembly, the wizard is working fine and I get all the code generated, except for the binding and the endpoint address - which is new to me. Before the change to the service, there were no additional parameters for the constructor of my service client neccessary.

When I create a client with the following code and make a call to the api

var binding = new BasicHttpsBinding();
var ep = new EndpointAddress(@"https://(my domain)/UpdateService.svc");
var svc = new AirCU.Service.UpdateServiceClient(binding, ep);

I get the exception There was no endpoint listening at https://(my domain)/UpdateService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."

I guess somewhere there is an issue in my configuration, either client or server...

What do I need to change in order to get everything back working? :)

Thanks a lot



Solution 1:[1]

Okay I figured it out myself.

Xamarin and .Net Standard do not support wsHttpEndpoints. I had to switch to a basicHttpsBinding, Xamarin does not support security mode TransportWithMessageCredential, so I had to stick with Transport only.

In the end my Web.config section looks like this:

<system.serviceModel>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>
    <services>
        <service name="aircu_web.UpdateService" behaviorConfiguration="debug">
            <endpoint address="" name="HttpsEndpoint" binding="basicHttpsBinding" bindingConfiguration="ServiceBinding" contract="aircu_web.IUpdateService" />
        </service>
    </services>
    <bindings>
        <basicHttpsBinding>
            <binding name="ServiceBinding" maxReceivedMessageSize="1000000">
                <security mode ="Transport">
                    <message clientCredentialType="UserName"/>
                </security>
            </binding>
        </basicHttpsBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="production">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
            <behavior name="debug">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceCredentials>
                    <serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="84 d2 c6 d8 85 17 48 30 04 9e 12 e0 bd f4 f3 36 c1 57 b5 6e" storeName="My"/>
                    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="aircu_web.ApiKeyValidator,aircu_web"/>
                </serviceCredentials>
                
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>

I also had to change my client code accordingly.

private UpdateService.UpdateServiceClient GetProxy()
    {
        var binding = new BasicHttpsBinding();
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
        binding.Security.Mode = BasicHttpsSecurityMode.Transport;
        var ep = new EndpointAddress(@"https://(mydomain)/UpdateService.svc");
        var svc = new UpdateService.UpdateServiceClient(binding, ep);
        svc.ClientCredentials.UserName.UserName = "App";
        svc.ClientCredentials.UserName.Password = "****";
        return svc;
    }

I also had to move my service reference from my library project to my xamarin project, because there was some assembly mismatching of the System.ServiceModel libraries I could not figure out.

I tried installing the same nuget packages to all project, removing them, clearing bin and obj folders, re-creating the project - nothing worked. So I moved the whole service reference to the xamarin project and now it works fine. Maybe someone can tell me what went wrong there. The Error was "Type (some number) unknown...."

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user16060704