Today I had to figure out how to query a SharePoint 2013 REST service from another domain.
It took a while to find the correct settings. 😉
There was no list on the internet so I want to post it here as reference. – If you have additions to it please post them in the comments.
My test bed:
- I created two web applications
- http://fromhere.kc-dev.com => Here I run the script that consumes data from the next web app
- http://tohere.kc-dev.com => This web app has some sub webs that I want to enlist on the first web app
- At the root of both web apps I created a “Team Site” site collection.
- I uploaded a copy of jQuery to the masterpage catalog of http://fromhere.kc-dev.com .
- Also to the masterpage catalog of this site I uploaded a script file named “crosssitescripting.js” containing the REST call to http://tohere.kc-dev.com/_api .
- On the homepage of the root site collection of http://fromhere.kc-dev.com I added some script tags to load the script files jQuery.js and crosssitescripting.js. And a div tag for the sub web list.
I opened the homepage of http://fromhere.kc-dev.com in the browser and got an error in the F12 dev tools of the Internet Explorer. As expected.
Now I added some web.config modifications using PowerShell to enable cross site scripting. (Some years ago I wrote a note on that topic: https://blog.kenaro.com/2010/09/02/add-web-config-modification-with-powershell-spwebconfigmodification)
After reloading the site I could see the sub web list:
Here is the content of crosssitescripting.js
$(document).ready(function(){ $.support.cors = true; $.ajax({ url: "http://tohere.kc-dev.com/_api/Web/Webs", type: "GET", crossDomain: true, dataType: "json", headers: { "Accept": "application/json; odata=verbose" }, xhrFields: { withCredentials: true }, success: function (response) { var ul = $("#weblist").append("<ul/>"); $(response.d.results).each(function(){ $("<li>"+this.Url+"</li>").appendTo(ul); }); }, error: function (xhr, status) { debugger; } }); });
Here is the PowerShell script to add the web.config modifications:
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA 0 $localFarm = Get-SPFarm $webapp = Get-SPWebApplication "http://tohere.kc-dev.com" # Remove old web.config modifications of MyAuthenticationProvider $oldMods = @(); $webapp.WebConfigModifications | ? { $_.Owner -eq "CrossSiteScripting" } | % { $oldMods = $oldMods + $_ } $oldMods | % { $webapp.WebConfigModifications.Remove($_) } # update the Web Application and apply all existing web.config modifications - this executes the "remove" actions from above $webapp.Update() [Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications() #Wait until web.config modifications finished by timer job while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) { Write-Host "." -NoNewline Start-Sleep 1 } # New web.config modifications for MyAuthenticationProvider $myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification $myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders" $myModification1.Name = "add[@name='Access-Control-Allow-Origin'][@value='http://fromhere.kc-dev.com']" $myModification1.Sequence = 0 $myModification1.Owner = "CrossSiteScripting" #0 = for the enum value "SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode" $myModification1.Type = 0 $myModification1.Value = "<add name='Access-Control-Allow-Origin' value='http://fromhere.kc-dev.com' />" $webapp.WebConfigModifications.Add($myModification1) $myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification $myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders" $myModification1.Name = "add[@name='Access-Control-Request-Method'][@value='GET,POST,HEAD,OPTIONS']" $myModification1.Sequence = 0 $myModification1.Owner = "CrossSiteScripting" $myModification1.Type = 0 $myModification1.Value = "<add name='Access-Control-Request-Method' value='GET,POST,HEAD,OPTIONS' />" $webapp.WebConfigModifications.Add($myModification1) $myModification1 = new-object Microsoft.SharePoint.Administration.SPWebConfigModification $myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders" $myModification1.Name = "add[@name='Access-Control-Request-Headers'][@value='Content-Type,Authorization']" $myModification1.Sequence = 0 $myModification1.Owner = "CrossSiteScripting" $myModification1.Type = 0 $myModification1.Value = "<add name='Access-Control-Request-Headers' value='Content-Type,Authorization' />" $webapp.WebConfigModifications.Add($myModification1) $myModification1 = new-objectMicrosoft.SharePoint.Administration.SPWebConfigModification $myModification1.Path = "configuration/system.webServer/httpProtocol/customHeaders" $myModification1.Name = "add[@name='Access-Control-Allow-Credentials'][@value='true']" $myModification1.Sequence = 0 $myModification1.Owner = "CrossSiteScripting" $myModification1.Type = 0 $myModification1.Value = "<add name='Access-Control-Allow-Credentials' value='true' />" $webapp.WebConfigModifications.Add($myModification1) $webapp.Update() [Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplyWebConfigModifications() #Wait until web.config modifications finished by timer job while( (Get-SPTimerJob | ? { $_.Name -eq "job-webconfig-modification"}) -ne $null ) { Write-Host "." -NoNewline Start-Sleep 1 }