<behaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <clientCertificate> <authentication customCertificateValidatorType="MyWS.Security.MyServicesCertificateValidator, MyWS" certificateValidationMode="Custom" revocationMode="NoCheck" /> </clientCertificate> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyWS.Security.MyServicesUsernameValidator, MyWS" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/> <bindings> <basicHttpBinding> <binding name="MySoapBinding"> <security mode="TransportWithMessageCredential"> <transport clientCredentialType="Certificate" /> <message clientCredentialType="UserName" /> </security> </binding> </basicHttpBinding> </bindings> <services> <service behaviorConfiguration="MyServiceBehavior" name="MyWS.Services.TheService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MySoapBinding" name="TheService" bindingNamespace="https://services.my/TheService" contract="MyWS.Interfaces.Service.ITheService" /> <host> <baseAddresses> <add baseAddress="https://localhost:4434/MyWS/TheService"/> </baseAddresses> </host> </service> </services>
private static Binding CreateMultiFactorAuthenticationBinding() { var httpsTransport = new HttpsTransportBindingElement(); // The message security binding element will be configured to require 2 tokens: // 1) A username-password encrypted with the service token // 2) A client certificate used to sign the message // Create symmetric security binding element with encrypted username-password token. // Symmetric key is encrypted with server certificate. var messageSecurity = SecurityBindingElement.CreateUserNameForCertificateBindingElement(); messageSecurity.AllowInsecureTransport = false; // Require client certificate as endorsing supporting token for all requests from client to server var clientX509SupportingTokenParameters = new X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient }; messageSecurity.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters); return new CustomBinding(messageSecurity, httpsTransport); }
//// Registering WCF-services var returnFaults = new ServiceDebugBehavior {IncludeExceptionDetailInFaults = true}; var metaData = new ServiceMetadataBehavior {HttpsGetEnabled = true}; var serviceCredentials = new ServiceCredentials(); // Configure service sertificate serviceCredentials.ServiceCertificate.SetCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "ServerCertificate"); // Configure client certificate authentication mode serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust; // Add custom username-password validator serviceCredentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; serviceCredentials.UserNameAuthentication.CustomUserNamePasswordValidator = _container.Resolve<MyServicesUsernameValidator>(); // Add custom certificate validator serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom; serviceCredentials.ClientCertificate.Authentication.CustomCertificateValidator = _container.Resolve<MyServicesCertificateValidator>(); var serviceModel = new DefaultServiceModel(); serviceModel.AddEndpoints( WcfEndpoint.ForContract<IMyContract>().BoundTo(CreateMultiFactorAuthenticationBinding())); serviceModel.BaseAddresses.Add(new Uri("https://server.com/MyServiceImplementation.svc")); serviceModel.AddExtensions(serviceCredentials); serviceModel.AddExtensions(metaData); _container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero) .Register(Component.For<IMyContract>() .ImplementedBy<MyServiceImplementation>() .AsWcfService(serviceModel), Component.For<IServiceBehavior>().Instance(returnFaults));