none
UserNamePasswordValidator not triggered in WCF RRS feed

  • Question

  • Hello everybody, 

    I'm currently looking into WCF for a new to build Webservice. I'm currently stuck on the UserNamePasswordValidator . It seems not be triggered, but I think everything seems to be OK in the code as far as I can see. I have the configuration of WCF configured in code, so I could ignore the config files and in the future I will get the address etc from the database. Currently I have the following code:

    Server:

    WSHttpBinding binding = new WSHttpBinding();
    
                binding.Security.Mode = SecurityMode.Message;
                binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
                
                // Create the URI for the endpoint.
                Uri httpUri = new Uri("http://127.0.0.1:1112/CloudService");
    
                // Create the service host.
                WebServiceHost = new ServiceHost(typeof(CloudService), httpUri);
                
                // Specify a certificate to authenticate the service.
                WebServiceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
                WebServiceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new MyApp.Webservice.Authentication();
                WebServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "LAPTOP01");
                WebServiceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
    
                WebServiceHost.AddServiceEndpoint(typeof(ICloudService), binding, "");
    
                // Add Metadata
                ServiceMetadataBehavior metadataBehavior =new ServiceMetadataBehavior();
                metadataBehavior.HttpGetEnabled = true;
                //metadataBehavior.HttpGetEnabled = true;
                WebServiceHost.Description.Behaviors.Add(metadataBehavior);
    
                WebServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
    
                Logging.WriteEventLog("The Webservice is started!", EventLogEntryType.Information, 1010);
                WebServiceHost.Open();
    

    Client:

    var _server = @"http://127.0.0.1:1112/CloudService";
                var binding = new WSHttpBinding(SecurityMode.Message);
                binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
    
                var address = new System.ServiceModel.EndpointAddress(_server);
    
                _client = new CloudServiceClient(binding, address);
                
                var username = "username";
                var password = "password";
    
         _client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
                    System.ServiceModel.Security.X509CertificateValidationMode.None;
    
                _client.ClientCredentials.UserName.UserName = username;
                _client.ClientCredentials.UserName.Password = password;
    
                _client.Open();
    

    Now I've tried multiple thing, but I can't seem to get it to work. Does anyone has any idea where I go wrong with my code? There is a certificate which works and also a custom validator, but it never seems to get there! Hope any one can help me, oh, and the error to make it complete:

    The caller was not authenticated by the service.

    InnerException : The request for security token could not be satisfied because authentication failed.

    Hope to hear from you soon and that you can help me!

    Monday, June 10, 2013 3:38 PM

Answers

  • Here is a walkthrough on how to enable custom validation using a UserNamePasswordValidator through configuration: http://msdn.microsoft.com/en-us/library/aa702565.aspx.

    If you want to do it programmatically, try to set the following properties of the service behavior:

    WebServiceHost host = new ServiceHost(typeof(CloudService), httpUri);
                host.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
                host.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication.CustomUserNamePasswordValidator = new MyCustomValidator();

    Monday, June 10, 2013 9:17 PM

All replies

  • If you are using IIS to host your service the basic authentication is handled by IIS and the CustomUsernamePasswordValidator never gets called.

    The solution is to use TransportWithMessageCredential security mode and set the Message.ClientCredentialType property to "UserName":

          WSHttpBinding binding = new WSHttpBinding();
          binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
          binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

    Monday, June 10, 2013 3:55 PM
  • I have WCF hosted in a Windows Service and I need to get the username and password from the database, IIS is unfortunately not an option in this case. Hope you van help me!
    • Marked as answer by ewolters Monday, June 10, 2013 5:19 PM
    • Unmarked as answer by ewolters Monday, June 10, 2013 5:19 PM
    • Edited by ewolters Monday, June 10, 2013 5:20 PM
    Monday, June 10, 2013 4:07 PM
  • Here is a walkthrough on how to enable custom validation using a UserNamePasswordValidator through configuration: http://msdn.microsoft.com/en-us/library/aa702565.aspx.

    If you want to do it programmatically, try to set the following properties of the service behavior:

    WebServiceHost host = new ServiceHost(typeof(CloudService), httpUri);
                host.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
                host.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication.CustomUserNamePasswordValidator = new MyCustomValidator();

    Monday, June 10, 2013 9:17 PM