none
WCF/SOAP Impersanation Authentication Issues In IIS7: The caller was not authenticated by the service RRS feed

  • Question

  • Hi,

    I’m new to WCF and IIS so please bear with me if I’m asking silly/obvious questions. Been searching for a week and can’t find a solution anywhere on the web so hoping you experts can help.

    I’ve implemented a WCF Web Service and deployed it in IIS7. I would quite simply like any client (i.e. smart devices, desktops etc.) outside my windows environment, to be able to anonymously call my web service. IIS should accept the client request, and impersonate a specific windows account I’ve created on the “Windows Server 2008 R2 / IIS7.0” server and use that impersonated account to execute the web service methods. Some of the web service methods talk to a SQL Server 2008 R2 database which through windows authentication recognises the specific windows user account I’ve created. My eventual goal is to call the web service from an Android device, using the Ksoap2 library. However for a simple test case I’ve implemented a simple method, “Ping”, which takes in a String and concatenates it with the server’s time, then returns the concatenated string (No database trips involved yet).

    Using the WCFTestClient, on the web server, I’m able to see the web service and Invoke all its methods (including methods that access the database). However, when using the WCFTestClient from my desktop, which is not in any kind of domain belonging to the web server, I’m unable to invoke any of the web service methods although the WCFTestClient is able to see the web service and all its methods.

    I’ve tried many variations of enabling and disabling “Anonymous Authentication” and/or “ASP .NET Impersonation” in IIS7 on the web server and more-or-less always end up with the WCFTestClient working on the server but not from a remote client. My latest IIS configuration is as follows:

    • An application pool with .NET Framework Version = .NET Framework v4.0.30319, Managed Pipeline Mode = Classic
    • The application pool uses and “Identity” which is a custom windows user account & password
    • At the Application level: Anonymous Authentication and ASP .NET Impersonation are enabled currently, though I’ve also tried with just “Anonymous Authentication” using the Application Pool Identity.

    From a remote WCFTestClient, I add the web service, see its methods and try to execute the “Ping” method. This is the soap request the WCFTestClient generated (which is the same request generated if done on the server, except for the MessageID):

    <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">

      <s:Header>

        <a:Action s:mustUnderstand="1">http://tempuri.org/IService/Ping</a:Action>

        <a:MessageID>urn:uuid:d1211e5c-7de6-4863-b5ff-7c16dd9d75dd</a:MessageID>

        <a:ReplyTo>

          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>

        </a:ReplyTo>

      </s:Header>

      <s:Body>

        <Ping xmlns="http://tempuri.org/">

          <yourName>test</yourName>

        </Ping>

      </s:Body>

    </s:Envelope>

    When I invoke the Ping method, I get back the following error:

    The caller was not authenticated by the service.

    Server stack trace:

       at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)

       at System.ServiceModel.Security.SspiNegotiationTokenProvider.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 IService.Ping(String yourName)

       at ServiceClient.Ping(String yourName)

    Inner Exception:

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

       at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)

       at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)

    Here’s the web.config on my IIS7 server, for the application:

    <?xml version="1.0" encoding="UTF-8"?>

    <configuration>

     

      <system.web>

             <compilation debug="false" defaultLanguage="c#" targetFramework="4.0" />

            <identity impersonate="true" password="****" userName="****" />

      </system.web>

      <system.serviceModel>

        <bindings>

          <mexHttpBinding>

            <binding name="NewBinding0" />

          </mexHttpBinding>

        </bindings>

        <services>

          <service name="Domanin.Service">

            <clear />

            <endpoint address="" binding="wsHttpBinding" name="ws" contract="Domain.Service.IService" listenUriMode="Explicit" />

            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="NewBinding0" name="mex" contract="IMetadataExchange" listenUriMode="Explicit" />

            <host>

              <baseAddresses>

                <add baseAddress="http://localhost/Service/" />

              </baseAddresses>

              <timeouts openTimeout="00:05:00" />

            </host>

          </service>

        </services>

        <behaviors>

          <serviceBehaviors>

            <behavior>

              <serviceMetadata httpGetEnabled="true" />

              <serviceDebug includeExceptionDetailInFaults="true" />

            </behavior>

          </serviceBehaviors>

        </behaviors>

        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

      </system.serviceModel>

      <system.webServer>

        <modules runAllManagedModulesForAllRequests="true" />

           <defaultDocument>

                <files>

                    <add value="Service.svc" />

                </files>

            </defaultDocument>

            <security>

                <authorization>

                    <remove users="*" roles="" verbs="" />

                    <add accessType="Allow" users="*" roles="" />

                </authorization>

            </security>

            <tracing>

                <traceFailedRequests>

                    <add path="*">

                        <traceAreas>

                            <add provider="ASP" verbosity="Verbose" />

                            <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />

                            <add provider="ISAPI Extension" verbosity="Verbose" />

                            <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module" verbosity="Verbose" />

                        </traceAreas>

                        <failureDefinitions timeTaken="00:00:01" verbosity="Error" />

                    </add>

                </traceFailedRequests>

            </tracing>

      </system.webServer>

    </configuration>

    Wednesday, January 23, 2013 1:51 PM

Answers

  • Problem solved. It seems I needed to set the security mode = none, for my wsHttpBinding. See my (example) highlighted changes below:

      <system.serviceModel>

        <bindings>

          <mexHttpBinding>

            <binding name="NewBinding0" />

          </mexHttpBinding>

    <wsHttpBinding>

      <binding name="NewBinding1">

        <security mode="None" >

      </binding>

    </wsHttpBinding>

        </bindings>

        <services>

          <service name="Domanin.Service">

            <clear />

            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding1" name="ws" contract="Domain.Service.IService" listenUriMode="Explicit" />

            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="NewBinding0" name="mex" contract="IMetadataExchange" listenUriMode="Explicit" />

    Previously I had no bindingConfiguration for the wsHttpBinding, in which case the default was used, which apparently was: security mode = “Message”.

    • Marked as answer by jatechs Tuesday, January 29, 2013 2:37 PM
    Tuesday, January 29, 2013 2:37 PM

All replies

  • Hi,

    Please try with a real client(e.g console app) to test the service, there are some features are not supported by WCF Test Client(with Security: CardSpace , Certificate, and Username/Password). You can learn more here.

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, January 24, 2013 9:24 AM
    Moderator
  • Hi Haixia,

    Thanks for the tip but I'm not using any username/password features. The client sends an anonymous request to the service... It's IIS that impersonate a user to my knowledge, correct me if I'm wrong.

    Anyway I tried accessing the server from a client android app and I get more-or-less the same kind of authentication issues.

    Remember I mentioned that the WCFTestClient works from the server, just doesn't work when called from a remote client.

    Any other ideas?

    Incidentally I posed this question to the IIS forums and they said come here, lol.

    Thursday, January 24, 2013 10:04 AM
  • >>which is not in any kind of domain belonging to the web server

    Hi,

    If you want to call the servce from a different domain, you can use JavaScript to access resources at a different domain. Please refer a blog below.

    #Cross-Domain Calls for a WCF Service

    http://blog.davidtruxall.com/2012/03/12/cross-domain-calls-for-a-wcf-service/

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, January 25, 2013 2:11 AM
    Moderator
  • Problem solved. It seems I needed to set the security mode = none, for my wsHttpBinding. See my (example) highlighted changes below:

      <system.serviceModel>

        <bindings>

          <mexHttpBinding>

            <binding name="NewBinding0" />

          </mexHttpBinding>

    <wsHttpBinding>

      <binding name="NewBinding1">

        <security mode="None" >

      </binding>

    </wsHttpBinding>

        </bindings>

        <services>

          <service name="Domanin.Service">

            <clear />

            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding1" name="ws" contract="Domain.Service.IService" listenUriMode="Explicit" />

            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="NewBinding0" name="mex" contract="IMetadataExchange" listenUriMode="Explicit" />

    Previously I had no bindingConfiguration for the wsHttpBinding, in which case the default was used, which apparently was: security mode = “Message”.

    • Marked as answer by jatechs Tuesday, January 29, 2013 2:37 PM
    Tuesday, January 29, 2013 2:37 PM