Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 239457
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T20:35:12+00:00 2026-05-11T20:35:12+00:00

I’ve been trying to get WCF security working for my project, and have had

  • 0

I’ve been trying to get WCF security working for my project, and have had little luck. I’m trying to create a service that uses net.tcp as the binding, and does both message and transport security. Message security is done using username and password and transport security is done (supposedly!) using certificates.

For my development testing, I created my own certificate authority and placed this certificate in my computer’s trusted store (LocalMachine). I then created two certificates, each signed by my certificate authority, one for the service to use, and one for the client app to use. I placed both of these in the Personal store (My) in LocalMachine. Then, for testing I created a random certificate that wasn’t signed by my certificate authority (and therefore is untrusted) and placed that in the Personal store in LocalMachine. I used makecert to create these certificates.

I then configured the client app that connects to the service to use the invalid untrusted certificate as its client certificate. The service is set (supposedly) to check the client certificates using chain trust. However, this client is able to connect and successfully talk to the service! It should be being rejected, because its certificate is untrusted!

I don’t know what’s causing this behaviour, so I submit the issue to you guys to see what you make of it. Here are my WCF configurations:

Service conf:

<system.serviceModel>
    <services>
        <service behaviorConfiguration="DHTestBehaviour" name="DigitallyCreated.DHTest.Business.DHTestBusinessService">
            <endpoint address="" binding="netTcpBinding" contract="DigitallyCreated.DHTest.Business.IDHTestBusinessService" bindingConfiguration="DHTestNetTcpBinding" bindingNamespace="http://www.digitallycreated.net/DHTest/v1" />

            <host>
                <baseAddresses>
                    <add baseAddress="net.tcp://localhost:8090/"/>
                    <add baseAddress="http://localhost:8091/"/>
                </baseAddresses>
            </host>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DHTestBehaviour">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <serviceCredentials>
                    <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="DHTestMembershipProvider"/>
                    <serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=business.dhtestDHTest.com" />
                    <clientCertificate>
                        <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
                    </clientCertificate>
                </serviceCredentials>
                <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="DHTestRoleProvider" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <netTcpBinding>
            <binding name="DHTestNetTcpBinding">
                <security mode="TransportWithMessageCredential">
                    <message clientCredentialType="UserName"/>
                    <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign"/>
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
</system.serviceModel>

Client Conf:

<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="NetTcpBinding_IDHTestBusinessService" 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="TransportWithMessageCredential">
                    <transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
    <behaviors>
        <endpointBehaviors>
            <behavior name="DHTestBusinessServiceEndpointConf">
                <clientCredentials>
                    <clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=invalid"/>
                    <serviceCertificate>
                        <authentication revocationMode="NoCheck" trustedStoreLocation="LocalMachine"/>
                    </serviceCertificate>
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <client>
        <endpoint address="net.tcp://phoenix-iv:8090/" binding="netTcpBinding"
         behaviorConfiguration="DHTestBusinessServiceEndpointConf"
         bindingConfiguration="NetTcpBinding_IDHTestBusinessService"
         contract="DHTest.NetTcp.Business.IDHTestBusinessService"
         name="NetTcpBinding_IDHTestBusinessService">
            <identity>
                <dns value="business.dhtest.com" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

The client username/password auth code:

DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
client.ClientCredentials.UserName.UserName = "ratfink";
client.ClientCredentials.UserName.Password = "testpassword";

Thank you for your help in advance.

EDIT (2009/06/01):

One of my friends pointed me towards a blog that answers the question as to why this is occurring. Apparently, when you specify TransportWithMessageCredential is means exactly that: Transport with Message Credentials only. This is why my certificates are being ignored on the transport level.

However, I don’t consider the issue complete and closed, because I still want to do this. 🙂 I’m going to look into custom certificate validators that I think I can plug in and see if that works. I’ll get back to you all with the results.

EDIT (2009/06/08):

No, custom certificate validators don’t work either. WCF simply doesn’t call them.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-11T20:35:12+00:00Added an answer on May 11, 2026 at 8:35 pm

    I found a solution to my problem, however, it turned out to be a lot nastier than I expected.

    Basically, to achieve both Transport and Message credential checking you need to define a custom binding. (I found info to this effect here).

    I found the easiest way to do this is to continue doing your configuration in the XML, but at runtime copy and slightly modify the netTcp binding from the XML configuration. There is literally one switch you need to enable. Here’s the code on the service side and on the client side:

    Service Side

    ServiceHost businessHost = new ServiceHost(typeof(DHTestBusinessService));
    ServiceEndpoint endpoint = businessHost.Description.Endpoints[0];
    BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
    SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
    sslElement.RequireClientCertificate = true; //Turn on client certificate validation
    CustomBinding newBinding = new CustomBinding(bindingElements);
    NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
    newBinding.Namespace = oldBinding.Namespace;
    endpoint.Binding = newBinding;
    

    Client Side

    DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
    ServiceEndpoint endpoint = client.Endpoint;
    BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
    SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
    sslElement.RequireClientCertificate = true; //Turn on client certificate validation
    CustomBinding newBinding = new CustomBinding(bindingElements);
    NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
    newBinding.Namespace = oldBinding.Namespace;
    endpoint.Binding = newBinding;
    

    You’d think that’d be it, but you’d be wrong! 🙂 This is where it gets extra lame. I was attributing my concrete service methods with PrincipalPermission to restrict access based on roles of the service user like this:

    [PrincipalPermission(SecurityAction.Demand, Role = "StandardUser")]
    

    This started failing as soon as I applied the above changes. The reason was because the

    OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
    

    was ending up being an unknown, username-less, unauthenticated IIdentity. This was because there are actually two identities representing the user: one for the X509 certificate used to authenticate over Transport, and one for the username and password credentials used to authenticate at Message level. When I reverse engineered the WCF binaries to see why it wasn’t giving me my PrimaryIdentity I found that it has an explicit line of code that causes it to return that empty IIdentity if it finds more than one IIdentity. I guess it’s because it’s got no way to figure out which one is the primary one.

    This means using the PrincipalPermission attribute is out the window. Instead, I wrote a method to mimic its functionality that can deal with multiple IIdentities:

    private void AssertPermissions(IEnumerable<string> rolesDemanded)
    {
        IList<IIdentity> identities = OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] as IList<IIdentity>;
        if (identities == null)
            throw new SecurityException("Unauthenticated access. No identities provided.");
    
        foreach (IIdentity identity in identities)
        {
            if (identity.IsAuthenticated == false)
                throw new SecurityException("Unauthenticated identity: " + identity.Name);
        }
    
        IIdentity usernameIdentity = identities.Where(id => id.GetType().Equals(typeof(GenericIdentity))).SingleOrDefault();
        string[] userRoles = Roles.GetRolesForUser(usernameIdentity.Name);
    
        foreach (string demandedRole in rolesDemanded)
        {
            if (userRoles.Contains(demandedRole) == false)
                throw new SecurityException("Access denied: authorisation failure.");
        }
    }
    

    It’s not pretty (especially the way I detect the username/password credential IIdentity), but it works! Now, at the top of my service methods I need to call it like this:

    AssertPermissions(new [] {"StandardUser"});
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.