Jimmy the Dev

WCF is great but for some reason every time I want to do something with the config files my brain goes to fudge and unless I can find an explicit example, demonstrating what I want to do, that I can user by simply substituting MyClassNames into... and I've been looking for examples of what it is I'm trying to do here but haven't found anything yet...

In any case, currently I have a service which I'm configuring in code as follows:

// Create a new service
serviceHost = new ServiceHost(typeof(My.Server.Services.MyService));
ContractDescription contractDescription = ContractDescription.GetContract(typeof(IMyService));

// Create an empty BindingElementCollection to populate, then create a custom binding from it.
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());
WindowsStreamSecurityBindingElement wbe = new WindowsStreamSecurityBindingElement();
wbe.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
bindingElements.Add(wbe);
bindingElements.Add(new TcpTransportBindingElement());
CustomBinding binding = new CustomBinding(bindingElements);

// Add an endpoint with all of this to our serviceHost
EndpointAddress endpointAddress = GetEndpointAddress(port, name);
ServiceEndpoint serviceEndpoint = new ServiceEndpoint(
contractDescription,
binding,
endpointAddress);
serviceHost.Description.Endpoints.Add(serviceEndpoint);

// Create a custom credentials validator class and wrap this in
// a ServiceCredentials description
ServiceCredentials creds = new ServiceCredentials();
creds.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
creds.UserNameAuthentication.CustomUserNamePasswordValidator = new MyUserNameValidator();

// Remove the existing ServiceCredentials description from the service host
// and replace this with our new custom behavior so that credentials get
// validated against our My database rather than Active Directory
serviceHost.Description.Behaviors.Remove<ServiceCredentials>();
serviceHost.Description.Behaviors.Add(creds);

// Add a custom authorization policy to the service authorization behavior.
List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>();
policies.Add(new MyAuthorizationPolicy());
serviceHost.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();

So basically it's a TCP channel with it's own custom UsernamePasswordValidator and a custom IAuthorizationPolicy.

What I'd like to do is to :
(a) Put all of that in a config file somehow
(b) Add another endpoint (I think I'll need an additional endpoint for this) which is exactly the same as the above except that it uses Windows Authentication instead of the custom UsernamePasswordValidator... but everything else (including the custom IAuthorizationPolicy) would stay.

Could anyone point me to an example of how I might do (a)

Also, regarding (b) - my main objective here is to support both Windows authentication and a Username and Password form of authentication... Am I correct in assuming that this will require an additional endpoint (and consequently an additional port) Ideally I'd like to just have the service operating on a single port and kind of magically support both authentication types on that single port - but I didn't think this would be possible.

TIA for any help.

Jimmy


Re: Windows Communication Foundation (Indigo) Help with config files

Jimmy the Dev

Phew! I like these little conversations I have with myself online... In any case, I worked out how to put my existing setup into a configuration file at least:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceServiceBehaviors">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyService.Server.Services.MyServiceUserNameValidator, MyService.Server.Services"/>
</serviceCredentials>
<serviceAuthorization>
<authorizationPolicies>
<add policyType="MyService.Server.Services.MyServiceAuthorizationPolicy, MyService.Server.Services"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="usernamePasswordBinding">
<security authenticationMode="UserNameOverTransport"/>
<windowsStreamSecurity protectionLevel="EncryptAndSign"/>
<tcpTransport/>
</binding>
</customBinding>
</bindings>
<services>
<service name="MyService.Server.Services.MyServiceService"
behaviorConfiguration="MyServiceServiceBehaviors">
<endpoint address="net.tcp://localhost:8080/MyServiceService"
contract="MyService.Interfaces.IMyServiceService"
binding="customBinding"
bindingConfiguration="usernamePasswordBinding"/>
</service>
</services>

My only remaining problem then is to add an endpoint that supports Windows Authentication as well. This, as it turns out, is a bit of a stickler because the bit in the config above that injects my custom UsernamePasswordValidator is in a service behavior (not an endpoint behavior)... Is it just me or is that quite odd

Jimmy




Re: Windows Communication Foundation (Indigo) Help with config files

Jimmy the Dev

Ahhh... I think I'm finally starting to understand - so yes, that's a service behavior and that's the usernamePasswordValidator that the service will use WHEN username and password credentials are supplied/specified in the endpoint configuration but not otherwise - so it's quite irrelevant and doesn't need to considered (much less removed) when using Windows Authentication.

Thanks all for your input!

Jimmy