locked
WCF Custom Authentication - getting error "System.ServiceModel.Security.SecurityNegotiationException" RRS feed

  • Question

  • User919378809 posted

    Hi,

    I am trying to implement WCF custom authentication in my application.  When I trying to run the client I am getting error like as follows...

    System.ServiceModel.Security.SecurityNegotiationException: SOAP security negotiation with 'http://localhost:52195/Service.svc' for target 'http://localhost:52195/Service.svc' failed. See inner exception for more details. ---> System.IdentityModel.Tokens.SecurityTokenValidationException: The X.509 certificate CN=WCfServer chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. The signature of the certificate cannot be verified. at System.IdentityModel.Selectors.X509CertificateChain.Build(X509Certificate2 certificate) at System.IdentityModel.Selectors.X509CertificateValidator.ChainTrustValidator.Validate(X509Certificate2 certificate) at System.IdentityModel.Selectors.X509SecurityTokenAuthenticator.ValidateTokenCore(SecurityToken token) at System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken token) at System.ServiceModel.Security.TlsnegoTokenProvider.ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation) at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnNegotiationComplete(SspiNegotiationTokenProviderState sspiState, RequestSecurityTokenResponse negotiationRstr, RequestSecurityTokenResponse authenticatorRstr) at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState) at System.ServiceModel.Security.IssuanceTokenProviderBase`1.GetNextOutgoingMessage(Message incomingMessage, T negotiationState) at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout) --- End of inner exception stack trace --- Server stack trace: at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout) at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout) at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout) at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at SampleWCF.CustomAuthenticationService.IService.GetValue(String sValue) at SampleWCF.Controllers.HomeController.About() in C:\Users\SRAMACH6\Desktop\Sample .Net\SampleWCF\SampleWCF\Controllers\HomeController.cs:line 60 

    Please find the code snippet as follows

    namespace ServiceCustomAuthentication
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            string GetValue(string sValue);
    
            [OperationContract]
            string GetData(int value);
    
            [OperationContract]
            CompositeType GetDataUsingDataContract(CompositeType composite);
    
            // TODO: Add your service operations here
        }
    
    
        // Use a data contract as illustrated in the sample below to add composite types to service operations.
        [DataContract]
        public class CompositeType
        {
            bool boolValue = true;
            string stringValue = "Hello ";
    
            [DataMember]
            public bool BoolValue
            {
                get { return boolValue; }
                set { boolValue = value; }
            }
    
            [DataMember]
            public string StringValue
            {
                get { return stringValue; }
                set { stringValue = value; }
            }
        }
    }
    namespace ServiceCustomAuthentication
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
        public class Service : IService
        {
            public string GetData(int value)
            {
                return string.Format("You entered: {0}", value);
            }
    
            public CompositeType GetDataUsingDataContract(CompositeType composite)
            {
                if (composite == null)
                {
                    throw new ArgumentNullException("composite");
                }
                if (composite.BoolValue)
                {
                    composite.StringValue += "Suffix";
                }
                return composite;
            }
    
            public string GetValue(string sValue)
            {
                return ("Welcome to WCF security " + sValue);
            }
        }
    }
    namespace ServiceCustomAuthentication
    {
        public class UserAuthentication : UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                try
                {
                    if (userName == "test" && password == "test")
                    {
                        Console.WriteLine("Authentic User");
                    }
                }
                catch (Exception ex)
                {
                    throw new FaultException("Unknown Username or Incorrect Password");
                }
    
            }
        }
    }
    <system.serviceModel>
    		<behaviors>
    			<serviceBehaviors>
    				<behavior name="customBehaviour">
    					<serviceMetadata httpGetEnabled="true"/>
    					<serviceDebug includeExceptionDetailInFaults="true"/>
    
    					<!-- user defined 3 - Authentication - configure custom authenticaiton method information -->
    					<serviceCredentials>
    						<userNameAuthentication 
    							userNamePasswordValidationMode="Custom"
    						   customUserNamePasswordValidatorType="ServiceCustomAuthentication.UserAuthentication, ServiceCustomAuthentication"/>
    						
    						<!--user defined 4-->
    						<clientCertificate>
    							<authentication certificateValidationMode="PeerTrust"/>
    						</clientCertificate>
    						<serviceCertificate findValue="WCfServer"
    											storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
    						<!--user defined 4-->
    					</serviceCredentials>
    				</behavior>
    			</serviceBehaviors>
    		</behaviors>
    
    		<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    
    		<!-- user defined 1 - service information -->
    		<services>
    			<service name="ServiceCustomAuthentication.Service" behaviorConfiguration="customBehaviour">
    				<endpoint address="" binding="wsHttpBinding" contract ="ServiceCustomAuthentication.IService" bindingConfiguration="ServiceBinding"></endpoint>
    				<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
    			</service>
    		</services>
    
    		<!-- user defined 2 - binding information -->
    		<bindings>
    			<wsHttpBinding>
    				<binding name="ServiceBinding">
    					<security mode="Message">
    						<message clientCredentialType="UserName"/>
    					</security>
    				</binding>
    			</wsHttpBinding>
    		</bindings>
    	</system.serviceModel>

    And I created service certificate as per the instruction in the following site

    http://www.codeproject.com/Articles/36683/simple-steps-to-enable-X-certificates-on-WCF

    Client - Asp.Net

    <system.serviceModel>
        <bindings>
          <wsHttpBinding>
            	<!--user defined bindings for custom authentication-->
    		  <binding name="customWsHttpBinding">
    			  <security mode="Message">
    				  <message clientCredentialType="UserName"/>
    			  </security>
    		  </binding>
    		  
          </wsHttpBinding>
        </bindings>
    	  
        <client>
          <endpoint address="http://localhost:52195/Service.svc" binding="wsHttpBinding"
    				contract="CustomAuthenticationService.IService" name="WSHttpBinding_IService" 
    				behaviorConfiguration="customBehaviour" bindingConfiguration="customWsHttpBinding">
            <identity>
              <certificate encodedValue="AwAAAAEAAAAUAAAAH6cdarAoIY735j/avW8JgrqpNiMgAAAAAQAAALUBAAAwggGxMIIBX6ADAgECAhCuYiT541X/s0kEkFRU4+BSMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMTQwNDE4MTgwNjM4WhcNMzkxMjMxMjM1OTU5WjAUMRIwEAYDVQQDEwlXQ2ZTZXJ2ZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK2ZWDO+z+TxLsCKUAOv7wDOKicEx07BgB92WrAyO41Rt27gtjqWwJ8hrM2ot7XXf2b+bwmFhj6Zxr76HdGdXpZMS9PPuoDXePKZqHt8Fw5CUE17inERA1mVa8mGGyyqC360FFOAz5H6sQHT4L25CMcd9qKwaYmCr1DL9BudV365AgMBAAGjSzBJMEcGA1UdAQRAMD6AEBLkCS0GHR1PAI1hIdwWZGOhGDAWMRQwEgYDVQQDEwtSb290IEFnZW5jeYIQBjdsAKoAZIoRz7jUqlw19DAJBgUrDgMCHQUAA0EAKyzmgx6XiaUTSHFG0+k0JGVJLLPDXETZoZ6P6er7wwIUF8ku2bqoy9rBZObIB50zcO5ybcfdudeZ9YxTorvcdQ==" />
            </identity>
          </endpoint>
        </client>
    
    	<!--user defined for custom authentication-->
    	  <behaviors>
    		  <endpointBehaviors>
    			  <behavior name="customBehaviour">
    				  <clientCredentials>
    
    					  <clientCertificate findValue="WCfClient" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
    
    					  <serviceCertificate>
    						  <authentication certificateValidationMode="PeerTrust" revocationMode="NoCheck"/>
    					  </serviceCertificate>
    					  
    				  </clientCredentials>
    			  </behavior>
    		  </endpointBehaviors>
    	  </behaviors>
    	  
    	  
    	  
      </system.serviceModel>
    try
                {
                    var myBinding = new WSHttpBinding();
                    myBinding.Security.Mode = SecurityMode.Message;
                    myBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
    
                    var myEndpoint = new EndpointAddress("http://localhost:52195/Service.svc");
    
                    var myChannelFactory = new ChannelFactory<SampleWCF.CustomAuthenticationService.IService>(myBinding, myEndpoint);
                    myChannelFactory.Credentials.UserName.UserName = "test";
                    myChannelFactory.Credentials.UserName.Password = "test";
    
                    var client = myChannelFactory.CreateChannel();
    
                    ViewData["Message"] = client.GetValue("Selvakumar Ramachandran");
                }
                catch (Exception ex)
                {
                    ViewData["Message"] = ex.ToString();
                }

    but not sure what is wrong in my code.  Can anyone help me to solve this issue?

    Monday, April 28, 2014 9:53 AM

All replies

  • User364480375 posted

    Try changing <userPrincipalName value="MACHINENAME\ASPNET" /> to <servicePrincipalNamevalue="host/localhost" /> in the client config file.

    Monday, April 28, 2014 1:31 PM
  • User919378809 posted

    Thanks for your reply.  I changed the config file but not working.  I am getting the same error.

    Monday, April 28, 2014 2:38 PM