Cross Site Scripting with SharePoint 2013 REST calls

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:

  1. I created two web applications
  2. At the root of both web apps I created a “Team Site” site collection.
  3. I uploaded a copy of jQuery to the masterpage catalog of http://fromhere.kc-dev.com .
  4. 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 .
  5. 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.

clip_image001

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.

clip_image002

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:

clip_image003

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
}

10 thoughts on “Cross Site Scripting with SharePoint 2013 REST calls

  1. This won´t work in FireFox if async is set to false. Other browsers do not have this problem.

  2. Hi Karstien,

    This is useful,

    Actually I am trying to perfrom Get call to REST api of JAVA application so that data can displayed on SharePoint i am able to do this earlier by enabling some thing using powershell command butnow i lost that link can you please suggest me.

    write now i am getting error acces denied

  3. Hi,

    I read your article followed the steps you mentioned here. I am getting access denied error still.

    We have one Site collection(Team Site) and another Site collection(My Site).

    We need list items from team site to show in My Site pages.

    I tried in IE11, its not help me. Using SystemAccount.
    Kindly help me any permission settings i missed here if so.

    Thanks in advance

  4. IE gives the security warning ”the page is accessing information that is not under its control This poses a security risk Do you want to continue?”…how to suppress this message..although we can do that by lower the rowser security settings..but i dont want to force every user to do so….

  5. Thanks for posting the PS script.

    I seem to be getting an error with the pre-flight (options) request.

    X-Forms_Based_Auth_Required:http://target.webapp.url/_login/default.aspx?ReturnUrl=/_layouts/15/error.aspx&Source=http://source.webapp.url/

    X-MSDAVEXT_Error:917656; Access denied. Before opening files in this location, you must first browse to the web site and select the option to login automatically.

    It looks the the response is asking the request to be authenticated, but we are using windows authentication. Has anyone else had this issue?

  6. Thanks for your good article.
    But i have some different issue, How to get data from SharePoint host header site collection to another host header site collection with in same Web application?
    Please help.

  7. Hi Karstien,
    This is useful,

    I’m so new and worried about how to do it powershell, can you take a video and share it
    thank you soo much

  8. Pingback: SharePoint CORS fix | For the love of challenges :)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.