7

I would like to access listdata.svc (a sharepoint service) located on domainA.contoso.com from a web application located on domainB.contoso.com - Authentication seems to be an issue.

When attempting to access ListData.svc via a JQuery Ajax call, with CORS enabled, the server returns 401. If I run the same Query from an .htm page which I execute from inside of SharePoint, the call works fine, since the domain is the same.

SharePoint is using NTLM with anonymous authentication turned off - I presume that the 401 is a result of windows credentials not being passed to the SharePoint server - but I am at a loss of how to add these credentials properly to the header. I have set xhrFields: { withCredentials: true }, but this does not seem to correct the authentication issue.

To enabled CORS, I have set the following HTTP Response Headers on SharePoint in IIS:

  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Headers:Origin, Content-Type, Accept
  • Access-Control-Allow-Origin: *
  • Access-Control-Request-Methods: POST, GET, HEAD, OPTIONS

Windows Authentication is enabled in IIS for my web application, and I did not set the "OPTIONSVerbHandler" HTTP Handler in IIS. Turning it to read doesn't seem to make a difference.

JQuery Ajax call (from application on subdomainB.contoso.com):

 $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        url: listUrl,
        xhrFields: { withCredentials: true },
        crossDomain:true,  
        processData: false,
        async: true,
        dataType: "json",
        converters: {
            // WCF Data Service .NET 3.5 incorrectly escapes singles quotes, which is clearly
            // not required (and incorrect) in JSON specs.
            // http://bugs.jquery.com/ticket/8320?cversion=0&cnum_hist=1
            "text json": function (textValue) {
                return jQuery.parseJSON(textValue.replace(/(^|[^\\])\\'/g, "$1'"));
            }
        },
        success: function (data, status, xhr) {
            //successFunc(data.d.results);
            alert("working!");
        },
        error: function (xhr, status, error) {
            alert("failure!");
        }
    });

HTTP Header and 401 Response:

Key Value
Request OPTIONS /_vti_bin/ListData.svc/Contacts HTTP/1.1
Accept  */*
Origin  http://domainB.contoso.com
Access-Control-Request-Method   GET
Access-Control-Request-Headers  content-type, accept
Accept-Encoding gzip, deflate
User-Agent  Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)
Host    domainA.contoso.com
Content-Length  0
DNT 1
Connection  Keep-Alive
Cache-Control   no-cache

Key Value
Response    HTTP/1.1 401 Unauthorized
Server  Microsoft-IIS/7.5
SPRequestGuid   1e33061c-f555-451b-9d69-0d83eff5f5ea
WWW-Authenticate    NTLM
X-Powered-By    ASP.NET
MicrosoftSharePointTeamServices 14.0.0.4762
Access-Control-Allow-Headers    Origin, Content-Type, Accept
Access-Control-Allow-Origin *
Access-Control-Request-Methods  POST, GET, HEAD, OPTIONS
Access-Control-Allow-Credentials    true
Date    Wed, 15 May 2013 15:04:51 GMT
Content-Length  0
Ray
  • 1,422
  • 2
  • 21
  • 39

3 Answers3

3

Late response, but I found another thread here which has an easy solution for IIS and which worked for me.

Basically the CORS standard specifies that a preflight request should not send any authentication information, thus the 401. In that thread there's an example of restricting anonymous requests to the OPTIONS verb which allows a 200 response to the preflight (OPTIONS verb) request but still requires the authentication for the others.

LarryDavid
  • 736
  • 6
  • 16
0

I'm not sure what you mean by "anonymous authentication is disabled", but it sounds like that's exactly the reason you're getting a 401 (Unauthorized) response. It's not related to CORS, but the server is telling the client it requires a username and a password before it will allow access.

Try passing a username and password to $.ajax() (WARNING: it's just to test if that solves your problem, hardcoding such details in your JS code is a Bad Idea):

$.ajax({
  crossDomain:true,    
  url: listUrl,
  username: VALID_USERNAME,
  password: VALID_PASSWORD,
  success: function(data){alert("hello json!") },
  error: function() {
    alert("epic fail");
  },
  dataType:'json'
});
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • anonymous auth is one of the modes switched off in IIS. Normally sharepoint uses Windows Auth. – Ray May 14 '13 at 18:41
  • @Ray thanks for the clarification :) I don't know if that affects passing the `username`/`password` properties to `$.ajax()`. – robertklep May 14 '13 at 18:48
  • I updated the question - using either username / password, or withCredentials, doesn't seem to work. – Ray May 15 '13 at 15:06
0

You can't use wildcard (*) for Access-Control-Allow-Origin on the server when client sends "withCredentials: true".
You must set the domain explicitely.
CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true

frenchone
  • 1,547
  • 4
  • 19
  • 34