.NET Framework Developer Center >
.NET Development Forums
>
Windows Communication Foundation
>
netTCP - the caller was not authenicated by the service
netTCP - the caller was not authenicated by the service
- I have a functional windows service that hosts a WCF over netTCP. The service uses message level security with clientCredentialType of certificate: Host config:
<system.serviceModel> <services> <service behaviorConfiguration="chainBehavior" name="MyCompany.Services.AuthenticationService"> <endpoint bindingConfiguration="tcpCertificateSecured" binding="netTcpBinding" contract="MyCompany.ServiceContracts.IAuthenticationService"> <identity> <dns value="My Client Cert" /> </identity> </endpoint> </service> </services> <bindings> <netTcpBinding> <binding name="tcpCertificateSecured"> <security mode="Message"> <message clientCredentialType="Certificate" /> </security> </binding> </netTcpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="chainBehavior"> <serviceCredentials> <clientCertificate> <authentication certificateValidationMode="ChainTrust" includeWindowsGroups="False" revocationMode="NoCheck"/> </clientCertificate> <serviceCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
The client passes the certificate, "My Client Cert", over as specified in the client config:
<system.serviceModel> <bindings> <netTcpBinding> <binding name="NetTcpBinding_IAuthenticationService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <message clientCredentialType="Certificate" /> </security> </binding> </netTcpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="chainBehavior"> <clientCredentials> <clientCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> <serviceCertificate> <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> <client> <endpoint address="net.tcp://localhost:6968/" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IAuthenticationService" contract="MyCompany.ServiceContracts.IAuthenticationService" name="IAuthenticationService" behaviorConfiguration="chainBehavior"> <identity> <dns value="My Client Cert" /> </identity> </endpoint> </client> </system.serviceModel>
The "My Client Cert" is generated from a home spun trusted certificate CA on the service host server and exists in the local machine personal store of the server and deployed to the local machine personal store of all the clients that will be connecting to the service host. The trusted certificate CA is placed in the Trusted Root Certificate authority on the service host server. These cannot be moved as the certificates are already deployed in the certificate stores of clients and servers in the field
When a client connects up to the host service for the first time, it fails with:
"the caller was not authenicated by the service"
if I restart the host service, the client connects and authenticates properly. This is unacceptable though as multiple clients will need to connect to this service and having to restart for each one would be disruptive to those that are already connected.
If I change the clientCredentialType to "None" it all works on the first go but this is not doing any real certificate security. Any suggestions on how to get ChainTrust to work correctly?
Answers
Hi,
first.
1.You can change the certificateValidationMode="PeerOrChainTrust".
if this does not work.
please make a certificate and set it trusted by Trusted CA and Trusted People. in client and Server.
This issues mat help you .
http://social.msdn.microsoft.com/Forums/en/wcf/thread/6b2d6fca-7a0d-49e4-87ca-65e6b2529d4c
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum- Marked As Answer byRiquel_DongModeratorThursday, November 12, 2009 5:55 AM
- Success! Made a few changes to the config and things are now working with a custom X509CertificateValidator. Here's the class:
The service host config is the same as above with a change to the behaviors:public class MyCertificateValidator : X509CertificateValidator { private const X509RevocationMode ChainTrustRevocationMode = X509RevocationMode.NoCheck; private const StoreLocation AuthorityCertStoreLocation = StoreLocation.LocalMachine; private const StoreName AuthorityCertStoreName = StoreName.Root; private const string AuthorityCertThumbprint = "thethumbprintofmyCAcert"; static MyCertificateValidator() { X509ChainPolicy policy = new X509ChainPolicy(); policy.RevocationMode = ChainTrustRevocationMode; } public override void Validate(X509Certificate2 certificate) { if(certificate==null) throw new SecurityTokenValidationException("No Certificate was passed"); X509Store store = new X509Store(AuthorityCertStoreName, AuthorityCertStoreLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, certificate.IssuerName.Name, true); if (certs.Count != 1) throw new SecurityTokenValidationException("Cannot find the root authority certificate"); X509Certificate2 rootAuthorityCert = certs[0]; if (String.Compare(rootAuthorityCert.Thumbprint, AuthorityCertThumbprint, true) != 0) throw new SecurityTokenValidationException("Not signed by our certificate authority"); store.Close(); } }
<serviceBehaviors> <behavior name="chainBehavior"> <serviceDebug includeExceptionDetailInFaults="True" /> <serviceSecurityAudit messageAuthenticationAuditLevel="SuccessOrFailure" serviceAuthorizationAuditLevel="SuccessOrFailure" auditLogLocation="Application"/> <serviceCredentials> <clientCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Security.MyCertificateValidator, Security" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" /> </clientCertificate> <serviceCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> </serviceCredentials> </behavior> </serviceBehaviors>
Likewise on the client:
Hope someone finds this useful as it was hard fought knowledge...<endpointBehaviors> <behavior name="chainBehavior"> <clientCredentials> <clientCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> <serviceCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Security.MyCertificateValidator, Security" trustedStoreLocation="LocalMachine" revocationMode="NoCheck"/> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors>
- Marked As Answer byRiquel_DongModeratorThursday, November 12, 2009 5:55 AM
All Replies
Hi,
first.
1.You can change the certificateValidationMode="PeerOrChainTrust".
if this does not work.
please make a certificate and set it trusted by Trusted CA and Trusted People. in client and Server.
This issues mat help you .
http://social.msdn.microsoft.com/Forums/en/wcf/thread/6b2d6fca-7a0d-49e4-87ca-65e6b2529d4c
Frank Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum- Marked As Answer byRiquel_DongModeratorThursday, November 12, 2009 5:55 AM
- Thanks for looking into this. In order to use the PeerOrChainTrust, the cert would need to be in trusted people store. Unfortunately I cannot move the certificates in our already deployed clients and servers.
This appears to be an issue with System.IdentityModel and the caching it does. As indicated above, If I recycle the appDomain of the service (restart), clinets can connect. This issue is covered here:
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/128c7f27-7626-49ac-8a92-daa45dcda0f1/
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/23455b64-6e69-461b-8a5b-08a17467d260
Its looking like I may need to write a custom validator to get around this. - So even wih a customCertificateValidatorType I still have to restart the service everytime a new clinet tries to connect up... Any suggestions on how to get around this?
- Success! Made a few changes to the config and things are now working with a custom X509CertificateValidator. Here's the class:
The service host config is the same as above with a change to the behaviors:public class MyCertificateValidator : X509CertificateValidator { private const X509RevocationMode ChainTrustRevocationMode = X509RevocationMode.NoCheck; private const StoreLocation AuthorityCertStoreLocation = StoreLocation.LocalMachine; private const StoreName AuthorityCertStoreName = StoreName.Root; private const string AuthorityCertThumbprint = "thethumbprintofmyCAcert"; static MyCertificateValidator() { X509ChainPolicy policy = new X509ChainPolicy(); policy.RevocationMode = ChainTrustRevocationMode; } public override void Validate(X509Certificate2 certificate) { if(certificate==null) throw new SecurityTokenValidationException("No Certificate was passed"); X509Store store = new X509Store(AuthorityCertStoreName, AuthorityCertStoreLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, certificate.IssuerName.Name, true); if (certs.Count != 1) throw new SecurityTokenValidationException("Cannot find the root authority certificate"); X509Certificate2 rootAuthorityCert = certs[0]; if (String.Compare(rootAuthorityCert.Thumbprint, AuthorityCertThumbprint, true) != 0) throw new SecurityTokenValidationException("Not signed by our certificate authority"); store.Close(); } }
<serviceBehaviors> <behavior name="chainBehavior"> <serviceDebug includeExceptionDetailInFaults="True" /> <serviceSecurityAudit messageAuthenticationAuditLevel="SuccessOrFailure" serviceAuthorizationAuditLevel="SuccessOrFailure" auditLogLocation="Application"/> <serviceCredentials> <clientCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Security.MyCertificateValidator, Security" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" /> </clientCertificate> <serviceCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> </serviceCredentials> </behavior> </serviceBehaviors>
Likewise on the client:
Hope someone finds this useful as it was hard fought knowledge...<endpointBehaviors> <behavior name="chainBehavior"> <clientCredentials> <clientCertificate findValue="My Client Cert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> <serviceCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Security.MyCertificateValidator, Security" trustedStoreLocation="LocalMachine" revocationMode="NoCheck"/> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors>
- Marked As Answer byRiquel_DongModeratorThursday, November 12, 2009 5:55 AM


