I'm trying to set up a custom IAuthorisationPolicy that I can give to ServiceAuthorizationBehaviour to install my own IPrincipal implementation. I've followed the instructions here, and written a test that verifies that this works when self-hosting using a NetNamedPipes binding.
The problem is, when I try to use this hosted under IIS the Identities property is not being set in the evaluationContext that is passed to my IAuthorisationPolicy (whereas it is when self-hosting).
The following is an extract from my configuration file:
<customBinding>
<binding name="AuthorisedBinaryHttpsBinding" receiveTimeout="00:03:00" sendTimeout="00:03:00">
<security authenticationMode="UserNameOverTransport">
</security>
<binaryMessageEncoding>
</binaryMessageEncoding>
<httpsTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CommonServiceBehaviour">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
membershipProviderName="AdminSqlMembershipProvider"/>
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</serviceBehaviors>
</behaviors>
(Note that I'm configuring the ServiceAuthorisationBehavior through code, which is why it doesn't appear here)
Any idea why I'm not being passed the Identities property?
My IAuthorisationPolicy looks like this:
public class PrincipalInstallingAuthorisationPolicy : IAuthorizationPolicy
{
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
var identity = GetClientIdentity(evaluationContext);
if (identity == null)
{
return false;
}
// var groups = get groups
var principal = new GenericPrincipal(identity, groups);
evaluationContext.Properties["Principal"] = principal;
return true;
}
private IIdentity GetClientIdentity(EvaluationContext evaluationContext)
{
object obj;
if (!evaluationContext.Properties.TryGetValue("Identities", out obj))
{
return null;
}
IList<IIdentity> identities = obj as IList<IIdentity>;
if (identities == null || identities.Count <= 0)
{
return null;
}
return identities[0];
}
...
}
I was working on the same issue. It may be because you use HTTP. In my case it is okay with the IIS and TCP binding. When i changed it to the basicHttpBinding the identitiy stoped to be sent.
One thing to check - do you really set the serviceAuthorization's principalPermissionMode to "Custom" (as shown in the article you linked to)? That's crucial for your success.
<serviceAuthorization principalPermissionMode="Custom">
Also - could it be that you're calling your service as an anonymous user? In that case, you might get a "null" identity.
What's you client config like?? What bindings do you use, what security settings?
Marc
Related
I have a WCF servcie set up with custom binding and a custom cert validator.
THe cert validator is defined as follows. It will be expanded later, but is just doing a basic verification currently.
public class MyX509CertificateValidator : X509CertificateValidator
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MyX509CertificateValidator));
public MyX509CertificateValidator()
{
Logger.Info("certval - Constructor ");
}
public override void Validate(X509Certificate2 certificate)
{
Logger.Info("certval - Validate(). Calling Cert.validate()");
bool verifyResult = certificate.Verify();
Logger.Info("verify result: " + verifyResult);
if (!verifyResult)
{
throw new SecurityTokenValidationException("cert had some bad juju");
}
}
}
My web.config is set up as follows. The goal is to use Transport security and use sessions. I want the cert to be validated once, when the session is being created. However, I can see through logging in the cert validator, that the validation takes place for every service call that a client makes, when using an existing open WCF client proxy.
I've verified that my WCF service instance is created once per session (logging in the constructor is being called once per session). But, the cert validator is being called every single service calls. How can I get the cert validator to be called only at the start of a session?
Given that it appears to be using sessions, I assumed that the cert verification would be sesssion-full, and invoked just once per session. I've perused the WCF configuration documentation on MSDN and do not see a way to further customize reliableSession tag, or anything related to Security to do what I wish.
Here's the web.config and the service definition
[ServiceBehavior(AutomaticSessionShutdown = true,
InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WcfBasicService : IWcfBasicService
{
...
<system.serviceModel>
<bindings>
<customBinding>
<binding name="reliableSessionOverHttps">
<reliableSession/>
<security authenticationMode="CertificateOverTransport"/>
<httpsTransport />
</binding>
</customBinding>
</bindings>
<services>
<service name="WcfServiceLibrary1.WcfBasicService">
<endpoint address="" binding="customBinding" contract="WcfServiceLibrary1.IWcfBasicService" name="mainEndpoint"
bindingConfiguration="reliableSessionOverHttps">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="WcfServiceLibrary1.MyX509CertificateValidator, WcfServiceLibrary1" />
</clientCertificate>
</serviceCredentials>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
AFAIK there is no any good WCF configuration solution for that, but you may implement some sort of cache inside Validate method, using Thumbprint property of the certificate (Thumbprint is actually hash of the certificate body):
public class MyX509CertificateValidator : X509CertificateValidator
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MyX509CertificateValidator));
private string lastValidCertTumbprint = null;
public MyX509CertificateValidator()
{
Logger.Info("certval - Constructor ");
}
public override void Validate(X509Certificate2 certificate)
{
if ((lastValidCertTumbprint != null) && (certificate.Tumbprint == lastValidCertTumbprint))
{
return; // Fast track
}
Logger.Info("certval - Validate(). Calling Cert.validate()");
bool verifyResult = certificate.Verify();
Logger.Info("verify result: " + verifyResult);
if (!verifyResult)
{
throw new SecurityTokenValidationException("cert had some bad juju");
}
// The cert valid, save this fact into fast track cache
lastValidCertTumbprint = certificate.Tumbprint;
}
}
I assume that session duration is far less then certificate lifetime and in case certificate(s) revoked, you have other means to terminate the sessions :)
To made things better, you may add some sort of timestamp of the last validation call and re-validate certificate if reasonable timeout (say, 30min) expired:
public class MyX509CertificateValidator : X509CertificateValidator
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MyX509CertificateValidator));
private string lastValidCertTumbprint = null;
private Stopwatch lastValidCertTimeMarker = new Stopwatch();
private const int VALIDATION_CACHE_LIFETIME = 30*60*1000; // in ms // 30min
public MyX509CertificateValidator()
{
Logger.Info("certval - Constructor ");
}
public override void Validate(X509Certificate2 certificate)
{
if ((lastValidCertTumbprint != null)
&& (certificate.Tumbprint == lastValidCertTumbprint)
&& (lastValidCertTimeMarker.ElapsedMilliseconds < VALIDATION_CACHE_LIFETIME))
{
return; // Fast track
}
lastValidCertTumbprint = null;
Logger.Info("certval - Validate(). Calling Cert.validate()");
bool verifyResult = certificate.Verify();
Logger.Info("verify result: " + verifyResult);
if (!verifyResult)
{
throw new SecurityTokenValidationException("cert had some bad juju");
}
// The cert valid, save this fact into fast track cache and save timestamp
lastValidCertTumbprint = certificate.Tumbprint;
lastValidCertTimeMarker.Reset();
lastValidCertTimeMarker.Start();
}
}
I have implemented a custom IDispatchMessageInspector, in order to parse one custom token type. After parsing the token I assign:
ServiceSecurityContext.Current.AuthorizationContext.Properties["ClaimsPrincipal"] = claimsPrincipal;
ServiceSecurityContext.Current.AuthorizationContext.Properties["Identities"] = identities;
Thread.CurrentPrincipal = claimsPrincipal;
I thought after ClaimsPrincipal got assigned in my IDispatchMessageInspector, It should have been available in my service method, unfortunately I've got a WindowsPrincipal(IsAuthentificated = false) there.
var currentIdentity = Thread.CurrentPrincipal as ClaimsPrincipal;
any thoughts?
Edit:
My web.config:
<services>
<service name="EchoService.TestEchoService">
<endpoint address="api" bindingConfiguration="secured" binding="webHttpBinding" behaviorConfiguration="rest" contract="EchoService.IEchoService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials useIdentityConfiguration="true">
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="echo.svc" factory="System.ServiceModel.Activation.ServiceHostFactory" service="EchoService.TestEchoService"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
<system.identityModel>
<identityConfiguration>
<securityTokenHandlers>
<clear/>
<add type="EchoService.Host.Tokens.SimpleWebTokenHandler,EchoService.Host"></add>
</securityTokenHandlers>
<audienceUris>
<clear/>
<add value="http://securitytestrealm/"/>
</audienceUris>
<issuerTokenResolver type="System.IdentityModel.Tokens.NamedKeyIssuerTokenResolver,System.IdentityModel.Tokens.Jwt">
<securityKey symmetricKey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=" name="YYYYYYYYYYYYYYYYYYY" />
</issuerTokenResolver>
</identityConfiguration>
Edit2:
Call sequence:
Contructor => GetTokenTypeIdentifiers => TokenType
In GetTokenTypeIdentifiers I return:
return new string[] { "http://schemas.microsoft.com/2009/11/identitymodel/tokens/swt" };
This sequence takes only place if I call my service first time.
The interesting thing that none of Handlers methods are being called when it is called after that.
Tokens should not be handled in IDispatchMessageInspector.
You need to implement SecurityTokenHandler that will allow you to read Token and extract whatever it carries => convert it to collection of claims and then return that collection. Provided claims collection will automatically be used to create ClaimsPrincipal by the WCF pipeline.
Check the link below:
http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.validatetoken.aspx
EDIT:
You have two possible approaches to add token handler to pipeline. One is to implement custom service host:
public class CustomServiceHost : ServiceHost
{
protected override void OnOpening()
{
base.OnOpening();
IdentityConfiguration identityConfiguration = new IdentityConfiguration();
identityConfiguration.SecurityTokenHandlers.Clear();
identityConfiguration.SecurityTokenHandlers.AddOrReplace(new CustomSecurityTokenHandler());
}
}
or via same xml segments in web.config:
http://msdn.microsoft.com/en-us/library/hh568671.aspx
EDIT:
ServiceCredentials credentials = this.Description.Behaviors.Find<ServiceCredentials>();
if (credentials == null)
{
credentials = new ServiceCredentials();
this.Description.Behaviors.Add(credentials);
}
credentials.UseIdentityConfiguration = true;
I was able to sort this thing out.
The only thing that was missing is one setting in web.config.
<serviceBehaviors>
<behavior>
<serviceAuthorization principalPermissionMode="None" />
Now it works as expected. Is there any security flaws?
Sorry, that's not how authentication in WCF works. You cannot simply assign Thread.CurrentPricipal from somewhere in the WCF processing pipeline and assume that WCF will automagically pickup that as a fact proving the user is authenticated.
You will need to hook into the right place of the pipeline. Which would be a serviceCredentials behavior.
Long story short:
My WCF clients should be able to provide both username and certificate to a service hosted in IIS, where I should use that information to validate requests using a custom policies.
Complete story:
I have the need to authenticate some WCF clients to verify if they can execute operations.
We have two kinds of clients: WPF applications and a web application. We would like to do the following:
The web application uses a certificate trusted by the service so that it is recognized as a special user with all permissions (the web application already verifies permissions by itself and we wouldn't like to touch it by now)
The WPF clients authenticate themselves with username/password provided by the user
In the implementation of the operations, I would like to verify if the certificate was provided (then I recognize the "super user"), otherwise fallback to username/password authentication.
Services are hosted in IIS 7 and we need to use NetTcpBinding.
I was able to implement the username validation, but the problem is that the AuthorizationContext inspected by the service contains only identity information, and not the certificate.
The following code is used on the client side to initialize the creation of channels (from a spike I'm using to test the solution):
var factory = new ChannelFactory<T>(this.Binding, address);
var defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials);
var loginCredentials = new ClientCredentials();
loginCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.None;
loginCredentials.UserName.UserName = username;
loginCredentials.UserName.Password = password;
if (useCertificate)
{
loginCredentials.SetCertificate();
}
factory.Endpoint.Behaviors.Add(loginCredentials);
return factory.CreateChannel();
With the SetCertificate extension being implemented like this:
public static void SetCertificate(this ClientCredentials loginCredentials)
{
loginCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "SecureWcfClient");
}
This is the configuration of the web application hosting the services:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SecureBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="Test"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<clientCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="AuthenticationProtectedService.Security.CertificateValidator, AuthenticationProtectedService.Security"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="AuthenticationProtectedService.Security.UserNamePassValidator, AuthenticationProtectedService.Security" />
</serviceCredentials>
<serviceAuthorization serviceAuthorizationManagerType="AuthenticationProtectedService.Security.CertificateAuthorizationManager, AuthenticationProtectedService.Security"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding>
<security mode="None"/>
</binding>
<binding name="SecureNetTcp">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<service
name="AuthenticationProtectedService.Services.OneWayServiceB"
behaviorConfiguration="SecureBehavior">
<endpoint
address=""
binding="wsHttpBinding"
contract="AuthenticationProtectedService.ServiceModel.IOneWayServiceB">
</endpoint>
</service>
<service
name="AuthenticationProtectedService.Services.DuplexServiceB" behaviorConfiguration="SecureBehavior">
<endpoint
address=""
binding="netTcpBinding"
bindingConfiguration="SecureNetTcp"
contract="AuthenticationProtectedService.ServiceModel.IDuplexServiceB">
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Finally, this is the implementation of the custom authorization manager (I also tried with a custom certificate validator but the function was never run)
public class CertificateAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
if (!base.CheckAccessCore(operationContext))
{
return false;
}
string thumbprint = GetCertificateThumbprint(operationContext);
// I'd need to verify the thumbprint, but it is always null
return true;
}
private string GetCertificateThumbprint(OperationContext operationContext)
{
foreach (var claimSet in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
foreach (Claim claim in claimSet.FindClaims(ClaimTypes.Thumbprint, Rights.Identity))
{
string tb = BitConverter.ToString((byte[])claim.Resource);
tb = tb.Replace("-", "");
return tb;
}
}
return null;
}
}
I think that the problem could be in the clientCredentialType property of the nettcpbinding.Security.Message node on the service configuration, but I don't see the option to use both Certificate and Username withing the Message security.
Any help appreciated, thanks
Remark: a specific goal of the project is to have very low level impact on server setup and in general in the system, so also SSL should be avoided if possible.
try out this link http://msdn.microsoft.com/en-us/library/ms733099.aspx ...it might resolve your issue where in you can have different binding configuration for same binding type and associate the same to different endpoints as per your need.
I have a service which is hosted in IIS. It is configured by Web.config.
I have created a custom UserNamePassValidator which works if I I have the logic in the validate method. But I want the logic in another project and injected in using DI as below.
public class UserNamePassValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
private readonly ISystemAuthentication _systemAuthentication;
public UserNamePassValidator(ISystemAuthentication systemAuthentication)
{
_systemAuthentication = systemAuthentication;
}
public override void Validate(string userName, string password)
{
_systemAuthentication.Validate(userName, password))
}
}
I am using the Autofac WCF integration.
var builder = new ContainerBuilder();
builder.RegisterType<AuthenticationService>().As<IAuthenticationService>();
builder.Register(c => new SystemAuthentication()).As<ISystemAuthentication>();
builder.Register(c => new UserNamePassValidator(c.Resolve<ISystemAuthentication>()));
AutofacHostFactory.Container = builder.Build();
When I browse to the service i receive the following error:
[MissingMethodException: No parameterless constructor defined for this object.]
web.config behaviour;
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I have read the following related post but the example is a self hosted service:
How to inject an object into a WCF validator class
EDIT
<system.serviceModel>
<services>
<service behaviorConfiguration="Namespace.AuthenticationServiceBehaviour" name="Namespace.AuthenticationService" >
<endpoint address="" binding="wsHttpBinding" contract="Namespace.IAuthenticationService" bindingConfiguration="SafeServiceConf">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Namespace.AuthenticationServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="AuthenticationService"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Namespace.UserNamePassValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SafeServiceConf" maxReceivedMessageSize="65536">
<readerQuotas maxStringContentLength="65536" maxArrayLength="65536" maxBytesPerRead="65536" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
SystemAuthentication class
public class SystemAuthentication : ISystemAuthentication
{
public bool Validate(string userName, string password)
{
// removed code for abbreviation
return true;
}
WCF Authentication Service
public class AuthenticationService : IAuthenticationService
{
public bool Authenticate(string email, string password)
{
// removed for abbreviation
return true;
}
}
From the help of this post UserNamePasswordValidator: When DI and Framework collide
From the XML configuraiton i removed:
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I added the behaviour to the AutoFacHostFactory service host
IContainer container = builder.Build();
AutofacHostFactory.Container = container;
AutofacHostFactory.HostConfigurationAction = host =>
{
var auth = host.Credentials.UserNameAuthentication;
auth.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
auth.CustomUserNamePasswordValidator = container.Resolve<UserNamePassValidator>();
};
This works perfectly, but it would have been nicer to be able to do it from the web.config. If anyone knows a better way please post :)
Hi,
I have set a WCF up as a webservice(percall), this webservice will getting request from a wide range of systems. Now we need somekind of way to identify the client.
Its possible to build a CustomUserNamePasswordValidation but this demands a secured(SLL) communication. In our case we do not need the security and the solution needs to be as easy as possible to setup.
So the question is how to send client identifikation(username/password) on each call?
I could place the identifikation data in the header but Im not sure how this can be tested with example soupUI? And Im not sure if all systems that will be communicate can handle this without complications?
Any sugestions?
Please note: I do only want to do 1 call, so no login service method should have to be used.
WCF do not suport sending user credentials unsecured. To solve this you could use the clear username binding or adding the credentials manually in the heador of the message(this is simple with WCF)
Define a binding in the web.config like :
<basicHttpBinding>
<binding name="BasicAuthBinding">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
Then define a service behaviour like :
<behavior name="Namespace.TestBehaviour">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Namespace.ServiceSecurity.UserAuthenticator, Namespace" />
</serviceCredentials>
<serviceAuthorization>
<authorizationPolicies>
<add policyType="Namespace.ServiceSecurity.MyAuthorizationPolicy, Namespace" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
Then provide the custom authentication and authorization classes as follows :
public class MyAuthorizationPolicy: IAuthorizationPolicy
{
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
IList<IIdentity> identities = (IList<IIdentity>) evaluationContext.Properties["Identities"];
foreach (IIdentity identity in identities)
{
if (identity.IsAuthenticated &&
identity.AuthenticationType == "UserAuthenticator")
{
evaluationContext.Properties["Principal"] = identity.Name;
return true;
}
}
if (!evaluationContext.Properties.ContainsKey("Principal"))
{
evaluationContext.Properties["Principal"] = "";
}
return false;
}
public ClaimSet Issuer
{
get { throw new NotImplementedException(); }
}
}
authentication as follows :
public class UserAuthenticator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
//authenticate me however you want
//then set whatever you want
}
}
If you need further security, change basicHttpBinding to a wsHttpBinding and use a certificate
EDIT : Almost forgot, use the defined service behaviour and binding in your service interface definition in web.config.
In the code :
public class WCF_Project_Authentification : UserNamePasswordValidator
{
#region UserNamePasswordValidator Interface Member
public override void Validate(string userName, string password)
{
if (userName != "Jeanc" || password != "fortin")
{
throw new FaultException("Authentification failed");
}
}
#endregion
}
In the config :
<behaviors>
<serviceBehaviors>
<behavior name="Service_Behavior">
<serviceMetadata httpGetEnabled="False" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WcfService.Authentification.WCF_Project_Authentification, WcfService"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
And in the client code :
proxy.ClientCredentials.UserName.UserName = "Jeanc";
proxy.ClientCredentials.UserName.Password = "fortin";