wshttp endpoint with message level security and custom password validator

I am trying ot get a wcf service running with message level security and
username/pw client credentials. When I try to make a call on my proxy it
throws an exception on the client:

Inner Exception: "The request for security token has invalid or malformed
elements."

Outer: "Secure channel cannot be opened because security negotiation with
the remote endpoint has failed. This may be due to absent or incorrectly
specified EndpointIdentity in the EndpointAddress used to create the channel.
Please verify the EndpointIdentity specified or implied by the
EndpointAddress correctly identifies the remote endpoint."

I have self signed certificate installed and configured - not sure where to
look for the problem:

here is my service config file:
********************

<configuration>
<system.serviceModel>
<services>
<service name="ExtranetWebService.ExtranetService"
behaviorConfiguration="extranetServiceBehavior">
<endpoint contract="ExtranetWebService.IExtranetService"
binding="wsHttpBinding">
</endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding"
address="mex" />
</service>
</services>

<behaviors>
<serviceBehaviors>
<behavior name="extranetServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true"/>
<serviceAuthorization principalPermissionMode="Custom"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="ExtranetWebService.CustomWCFUserNameValidator,ExtranetWebService"/>

<serviceCertificate findValue="XPS" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding" maxReceivedMessageSize="2000000">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>

and my client config file:
******************

<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IExtranetService"
maxReceivedMessageSize="2000000">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="true"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:80/ExtranetService"
behaviorConfiguration="ClientCertificateBehavior"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IExtranetService"
contract="ExtranetExplorer.ExtranetService.IExtranetService"
name="WSHttpBinding_IExtranetService">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>

I also turned on tracing to get more detail and here is a snippet from that:
************************************

<Message>Incoming binary negotiation has invalid ValueType
http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego.</Message><StackTrace>
at
System.ServiceModel.Security.BinaryNegotiation.Validate(XmlDictionaryString
valueTypeUriDictionaryString)
at
System.ServiceModel.Security.SspiNegotiationTokenAuthenticator.ValidateIncomingBinaryNegotiation(BinaryNegotiation incomingNego)
at
System.ServiceModel.Security.SspiNegotiationTokenAuthenticator.ProcessRequestSecurityToken(Message
request, RequestSecurityToken requestSecurityToken,
SspiNegotiationTokenAuthenticatorState&amp; negotiationState)
at
System.ServiceModel.Security.NegotiationTokenAuthenticator`1.ProcessRequestCore(Message request)

and my custom username validator class:
**************************

namespace ExtranetWebService
{
/// <summary>
/// used to authenticate users against eDefine security framework
/// </summary>
class CustomWCFUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == null || password == null)
{
throw new ArgumentNullException();
}

//check username and password
if(eDefine.Framework.Security.UserManager.Login(userName, password).Status
!= eDefine.Framework.Security.LoginStatus.Success)
{
throw new SecurityTokenException("ERROR: Unkown username or incorrect
password");
}
}
}
}

[5947 byte] By [miantosca] at [2008-1-2]
# 1

After using the SvcTraceViewer I was able to see the offending message which I thought might help shed some light on what might be wrong with it

HERE IT IS:

<MessageLogTraceRecord>
<HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<Connection>Keep-Alive</Connection>
<Content-Length>1155</Content-Length>
<Content-Type>application/soap+xml; charset=utf-8</Content-Type>
<Expect>100-continue</Expect>
<Host>localhost</Host>
</WebHeaders>
</HttpRequest>
<s:Envelope xmlnsTongue Tied="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:fa9ada57-85f6-47b8-8dab-8c305c49b7a6</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">http://localhost/ExtranetService</a:To>
</s:Header>
<s:Body>
<t:RequestSecurityToken Context="uuid-d5721b46-22ca-46fa-b3f9-3322e89716ca-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeySize>256</t:KeySize>
<t:BinaryExchange ValueType=" http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FgMBAFcBAABTAwFGHp4pHk7OU5hDwKnfroluSZNinvXB1LrCzznS2RqD9AAAGAAvADUABQAKwAnACsATwBQAMgA4ABMABAEAABIACgAIAAYAFwAYABkACwACAQA=</t:BinaryExchange>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>

miantosca at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 2

hi,

Please verify the EndpointIdentity specified or implied by the
EndpointAddress correctly identifies the remote endpoint

The server is providing a certificate to identity it self to any client.
in your case the client can not verify the identity of the server, because there is no

<certificate encodedValue ="zzz" in your client config.

I don't remember right now why this value is not generated for you by svcutil,
<ignore>a boolean value on the negotiateServiceCredential or the establishSecurityContext must be set to false</ignore>

depending on how you create your channel on the client side, you must provide a certificate reference, so if you
specify how the client can lookup the public key of the server in your client config file like this:

<client>
<endpoint
....
<identity>
<certificateReference findValue="XPS"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
</identity>
</endpoint>
</client>

it should work.

If you are using the channel factory pattern to create an instance of your service,
then you could use the EndpointIdentity class.

example:


EndpointAddress epa = new EndpointAddress(new Uri("..."), EndpointIdentity.CreateDnsIdentity("XPS"));
....
factory.CreateChannel(epa);

hth, Allan

Allan-Nielsen at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 3

Thanks Allan - I added the identity section with the certificate reference but it is still giving me the same error message.

I tried to regenerate the client config by updating my service reference and it is strange because the service does not seem to be emitting the correct configuration information.

Below is what it is generating when I tell VS.NET 2005 to update the service reference - notice the bolded Windows values in the clientcredentialtype attributes. The service has clientCredentialType="UserName" specified - why would the autogenerated config settings have Windows?

It is also strange - like you mentioned - why the service is not sending the encoded public key for the client to use for requests.

<system.serviceModel>

<bindings>

<wsHttpBinding>

<binding name="WSHttpBinding_IExtranetService" closeTimeout="00:01:00"

openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"

bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"

maxBufferPoolSize="524288" maxReceivedMessageSize="65536"

messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"

allowCookies="false">

<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

maxBytesPerRead="4096" maxNameTableCharCount="16384" />

<reliableSession ordered="true" inactivityTimeout="00:10:00"

enabled="false" />

<security mode="Message">

<transport clientCredentialType="Windows" proxyCredentialType="None"

realm="" />

<message clientCredentialType="Windows" negotiateServiceCredential="true"

algorithmSuite="Default" establishSecurityContext="true" />

</security>

</binding>

</wsHttpBinding>

</bindings>

<client>

<endpoint address="http://localhost/ExtranetService" binding="wsHttpBinding"

bindingConfiguration="WSHttpBinding_IExtranetService" contract="ExtranetExplorer.ExtranetService.IExtranetService"

name="WSHttpBinding_IExtranetService">

<identity>

<userPrincipalName value="XPS\Michael" />

</identity>

</endpoint>

</client>

</system.serviceModel>

miantosca at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 4

Michael,

when I look at your service config file, it has no bindingConfiguration for the wsHttpBinding which means it defaults.

this is why your client config file ends up like it does.

specify as bindingConfiguration on your endpoint

e.g

<endpoint contract="ExtranetWebService.IExtranetService"
binding="wsHttpBinding" bindingConfiguration="secureUserName"/>

<wsHttpBinding>
<binding name="secureUserName"

this will probably help Smile

I take it you're hosting your service in IIS hence you don't specify the address in your endpoint, please for me, do that, its just good pratice

hth, Allan

Allan-Nielsen at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 5

That worked!

I am not hosting in IIS - I am hosting in a console app - so I should add the http://localhost/ExtranetService/ as the address in the service config file?

thanks for helping me work through this.

Michael

miantosca at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 6

great,

yes unless you specify a host

<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ExtranetService/ "/>
</baseAddresses>
</host>

<endpoint address=""
binding="wsHttpBinding"
contract="IContract"
bindingConfiguration="secureBinding"/>

regards Allan

Allan-Nielsen at 2007-9-12 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...

Visual Studio Orcas

Site Classified