Username and password authentication for WCF service behind DMZ firewall

Scenario

Client and HTTPS -> DMZ Firewall Only - HTTP Only -> WCF Service

When a client tries to connect to the WCF service, it must do this via HTTPS (SSL). If it tries to connect via HTTP, the DMZ firewall redirects it to HTTPS anyway. When a request arrives at the DMZ firewall, it is redirected to the WCF service over an insecure connection (HTTP only).

I want my service to be protected by user name and password authentication, so I tried wsHttpBindingsetting it to TransportWithMessageCredentialboth user and user mode UserNamePasswordValidator.

My web.config file looks like

<system.serviceModel>
<services>
  <service name="WcfService1.TestWcfService" behaviorConfiguration="WcfService1.TestWcfServiceBehavior">
    <!-- Service Endpoints -->
    <endpoint address="" binding="wsHttpBinding" bindingName="wsHttpBinding_behind_firewall" contract="WcfService1.ITestWcfService">
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="WcfService1.TestWcfServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1.WcfAuthenticationValidator, WcfService1"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <wsHttpBinding>
    <binding name="wsHttpBinding_behind_firewall">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None" />
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
</system.serviceModel>

And my password verification class is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.ServiceModel;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;

namespace WcfService1
{
    public class WcfAuthenticationValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (userName == null)
            {
                throw new ArgumentNullException(nameof(userName));
            }

            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            //TODO: get username and password from DB and compare incoming password with one stored in DB.

            if (!(userName == "hello" && password == "world"))
            {
                throw new SecurityTokenException("Unknown Username or Incorrect Password");
            }
        }
    }
}

WCF, :

TestWcfService.TestWcfServiceClient client = new TestWcfService.TestWcfServiceClient();
client.ClientCredentials.UserName.UserName = "hello";
client.ClientCredentials.UserName.Password = "world";
Console.WriteLine(client.GetData(0));

app.config :

<system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="wsHttpBinding_behind_firewall_ITestWcfService" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://example.com/TestWcfService.svc"
                binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_behind_firewall_ITestWcfService"
                contract="TestWcfService.ITestWcfService" name="wsHttpBinding_behind_firewall_ITestWcfService">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

wsHttpBinding , WCF , HTTPS.

, HTTP HTTPS, . - ?

+4
1

web.config - http https.

- :

<bindings>
  <wsHttpBinding>

    <binding name="wsHttpsBindingConfig" >          
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="None">
        </transport>
      </security>

    </binding>
    <binding name="wsHttpBindingConfig" >
    </binding>
  </wsHttpBinding>
</bindings>

<services>
  <service name="WcfService1.Service1">
    <endpoint name="wsHttpBinding"
              contract="WcfService1.IService1"
              binding="wsHttpBinding" 
              bindingConfiguration="wsHttpBindingConfig"
              address=""  >          
    </endpoint>

    <endpoint name="wsHttpsBinding" 
              binding="wsHttpBinding" 
              bindingName="wsHttpBinding_secure"
              contract="WcfService1.IService1" 
              bindingConfiguration="wsHttpsBindingConfig"
              address="">
      <identity>

        <dns value="localhost"/>
      </identity>
    </endpoint>
  </service>   
+1

Source: https://habr.com/ru/post/1675681/


All Articles