Matt
Matt

Reputation: 26971

Passing NTLM credentials to remote web service

I would like to pass NTLM credentials to a remote web service.

I load my page from rm1.domain.com and in its Javascript, a web service on rm2.domain.com is called.

I would like the web service called to be able to read the NTLM credentials of the user doing the calling, but I am running into some issues.

Scenario A (won't work)

If I have the following in my config file:

 <webHttpEndpoint>
        <standardEndpoint name="" 
         automaticFormatSelectionEnabled="true" 
         crossDomainScriptAccessEnabled="true">
          <security>
            <transport clientCredentialType="Ntlm"></transport>
          </security>
       </standardEndpoint>
 </webHttpEndpoint>

and only Windows Authentication enabled in IIS, I get the expected:

enter image description here

Scenario B (won't work)

I have the following in my config file

<webHttpEndpoint>
  <standardEndpoint name="" automaticFormatSelectionEnabled="true">
      <security>
        <transport clientCredentialType="Ntlm"></transport>
      </security>
  </standardEndpoint>
</webHttpEndpoint>

and the following in my JavaScript:

jQuery.ajax({
    url: "http://rm2.domain.com/getInfo?name=bobsyouruncle,
    dataType: "json",
    async: false,
    success: function(data) {
        console.log('woot');
    },
    error: function(ex) {
        console.log(ex);
    }
});

and only Windows Authentication enabled in IIS, the browser throws:

If I change my JavaScript to JSONP, then I get nothing either, but that's not unexpected either as I removed crossDomainScriptAccessEnabled="true" from the web.config. But as you will see in scenario C, you can't have crossDomainScriptAccessEnabled="true" with an authentication scheme enabled.

Scenario C (won't pass credentials)

If mr2's web service's web.config is like scenario B, IIS authentication anonymous is enabled (and windows auth is disabled), and jQuery's request is JSONp then the service returns data, but the authentication information isn't passed.

Bottom Line (TL;DR) Is there a way to leave my web service as IIS anonymous, with the cross domain tag in its web.config, pass the domain (NTLM) credentials from the browser and parse them in my code-behind of my web service.

The documentation and sheer number of options is overwhelming and confusing.

Upvotes: 5

Views: 5704

Answers (3)

Fabio Beltramini
Fabio Beltramini

Reputation: 2511

Sorry, I don't know exactly what kind of data you're trying to pass, but if the only problem is a cross-domain ajax call, simply place a new HTML file on the target domain that will execute the ajax call on behalf of the calling page.

When you want to make the ajax call, insert a new iframe into the document pointing to the iframe location and passing the data in a query string.

function sendData(data){ var datastring=JSON.stringify(data); var el=document.createElement("iframe"); el.src="//rm2.domain.com/iframe.html?data="+encodeURIComponent(datastring); if(el.style){el.style.display="none";} document.body.appendChild(el); }

The iframe receives the data, makes the ajax call, and then sends the value back to the original page via a URL fragment:

<!DOCTYPE html>
<html lang="en-US">

<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
if(document.referrer=="rm1.domain.com" ){
    var querystring=window.location.search.split("&");
    var datastring="";
    var data;
    for(var q=0;q<querystring.length;q++){
        if(querystring[q].split("=")[0]=="data"){datastring=querystring[q].slice("data".length+1);}
    }
    if(datastring){data=JSON.parse(datastring);}

    jQuery.ajax({
        url: "/getInfo?name=bobsyouruncle",
        dataType: "json",
        data:data,
        async: false,
        success: function(data) {
            top.location="#data="+JSON.stringify(data);
        },
        error: function(ex) {
            top.location="#error="+JSON.stringify(ex);
        }
    });
}
</script>
</head>
</html>

The original page can periodically check (e.g. using a setInterval set when the iframe is added) for the data. If multiple requests need to be sent, the identifier of the interval to clear can also be passed. If you can restrict your user base to HTML5 compliant browsers, you have a less "hackish" method to pass the data back and forth in the window.postMessage method. All those extra details can be found here: http://softwareas.com/cross-domain-communication-with-iframes

Upvotes: 0

FlemGrem
FlemGrem

Reputation: 814

Have a look at this, there are some interesting points made on the use of NTLM and Impersonation.

The HTTP request is unauthorized with client authentication scheme 'Ntlm'

I know your question is not WCF specific, but some of the points raised bare relevance to your scenario.

The Last comment saying "authenticationScheme and proxyAuthenticationScheme to "Ntlm" is an interesting one for you.

Upvotes: 1

Kevin
Kevin

Reputation: 429

If you look at the traffic in an inspector like fiddler, is the proper handshake between the client and server taking place? When Windows Authentication is enabled there will be a response from the server with a header indicating the client (the browser) should send the NTLM token which the server accepts and goes on making the actual response.

If you host the web service on the same domain you may be able to isolate what sounds like two issues in order to solve the credential issue, and once that is working you can focus on the CORS issue.

To partially answer your question, an anonymous authenticated website will not request an NTLM (or Kerberos) token

Upvotes: 0

Related Questions