Question

I am trying to set up a WCF service that should be able to communicate with clients from Linux machines. The service should be able to support sessions so that I can keep track of the clients, as we are maintaining state for each client.

Since the clients will be coming in from networks other then the one where service is hosted, I am using custom UserNamePasswordValidator and ServiceAuthorization manager to authenticate clients.

If I use Security.Message.ClientCredentialType = MessageCredentialType.Windows, I can connect to my Service from a Windows machine, and a WCF session is established. Everything works fine till here.

However as I said in the beginning that I need to make it work with clients connecting from Linux, I tried to use SecurityMode.TransportWithMessageCredential and SecurityMode.Message. WCF asked me to encrypt the communicate using a certificate, which I did. However I can't get sessions to work. For each call from the client, the ServiceSecurityContext.Current.AuthorizationContext.Id is changed.

Can any please point out what should be changed in the following code to make it work with WCF sessions without using MessageCredentialType.Windows?

    private void SetupHTTPService()
    {
        string httpUrl = 
          String.Format("{0}://{1}:{2}/MyService", "http", m_httpEndpoint, m_httpPort);
        string wsdlUrl = 
          String.Format("{0}://{1}:{2}/MyService.API", "http", m_httpEndpoint, m_httpPort);

        Console.WriteLine("Listening on " + httpUrl);

        // Create the service host
        m_httpServiceHost = new ServiceHost(typeof(Server), new Uri(httpUrl));

        // Create the binding
        WSHttpBinding wsHttpBinding = new WSHttpBinding();
        wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
        wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

        // Attach the custom u/p validator
        // and the service authorization manager.
        m_httpServiceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =
            System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
        m_httpServiceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator =
            new CustomUserNameValidator();
        m_httpServiceHost.Authorization.ServiceAuthorizationManager = new CustomServiceAuthorizationManager();

        wsHttpBinding.Security.Mode = SecurityMode.Message;
        wsHttpBinding.ReliableSession.Enabled = true;
        SetCertificate(m_httpServiceHost);

        m_httpServiceHost.AddServiceEndpoint(typeof(IServer), wsHttpBinding, httpUrl);

        m_httpServiceHost.Open();
    }

    private void SetCertificate(ServiceHost serviceHost)
    {
        WCFPluginSection configuration = System.Configuration.ConfigurationManager.GetSection("WCFPlugin") as WCFPluginSection;
        if (configuration != null)
        {
            bool encryptCommunication = configuration.EncryptUsingCertificate;
            if (encryptCommunication)
            {
                StoreLocation storeLocation = configuration.CertificateStoreLocation;
                StoreName storeName = configuration.CertificateStoreName;
                string certificateName = configuration.CertificateName;
                if( storeLocation == 0 || storeName == 0 || String.IsNullOrEmpty(certificateName))
                    throw new Exception("Certificate settings are not valid!");

                serviceHost.Credentials.ServiceCertificate.SetCertificate(
                        storeLocation,
                        storeName,
                        X509FindType.FindBySubjectName,
                        certificateName);
            }
        }
    }

Bottom line is that if I use SecurityMode.TransportWithMessageCredential or SecurityMode.Message, WCF sessions are not working.

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top