Getting a Full Result Set from a Remote SharePoint Index in SharePoint 2013

This post is in follow up to a previous post about setting up an OAuth trust between two farms: https://blogs.technet.com/b/speschka/archive/2012/07/23/setting-up-an-oauth-trust-between-farms-in-sharepoint-2013.aspx. The primary reason for writing that post was to describe how to set up an OAuth trust between two farms, which can be used for a number of reasons. A secondary part of that post was to describe the process of setting up a Remote SharePoint Index, which is one of the top reasons why you would create that trust. What I have since discovered is that this type of trust by default will only return search results from the web application with which the trust is created. For example, as the post indicates you run some PowerShell that looks like this:

$i = New-SPTrustedSecurityTokenIssuer -Name FARMB -Description "Farm B" -IsTrustBroker:$false -MetadataEndPoint "https://farmb.foo.com/_layouts/15/metadata/json/1"
New-SPTrustedRootAuthority -Name FARMB -MetadataEndPoint https://farmb.foo.com/_layouts/15/metadata/json/1/rootcertificate
$p = Get-SPAppPrincipal -Site https://www.foo.com -NameIdentifier $i.NameId
Set-SPAppPrincipalPermission -Site https://www.foo.com -AppPrincipal $p -Scope SiteSubscription -Right FullControl

In this case, the results you would get back would only be those items that are contained in the https://www.foo.com web application. If you have multiple web applications, or other non-SharePoint content sources, they won't be returned in the search results when queried remotely. Side Note: this limitation does not exist when you are using Remote SharePoint Index in a hybrid situation between Office 365 and an on-premises SharePoint farm. So, how do we get results from all our web applications and content sources? Well there are two things we need to do: 1) create additional realms and grant the SPAppPrincipal permissions to it and b) when you grant permissions, set the scope to SiteCollection instead of SiteSubscription. 

Let's look at a concrete example: suppose you are in Farm A, and you have 3 web applications: https://portal.foo.com, https://teams.foo.com and https://my.foo.com. (Another side note: please don't interpret this to mean that you should have multiple web applications in SharePoint 2013 - you should try and use one web app and host name site collections, and add web apps if business requirements dictate). Farm A is going to trust Farm B, and Farm B is going to send queries to Farm A. In Farm A then, we need to set up a realm for each of the three web applications and grant permissions to the SPAppPrincipal that Farm B will use when issuing the queries. We'll start out with the first two lines of PowerShell, which are the same as our original post:

$i = New-SPTrustedSecurityTokenIssuer -Name FARMB -Description "Farm B" -IsTrustBroker:$false -MetadataEndPoint "https://farmb.foo.com/_layouts/15/metadata/json/1"
New-SPTrustedRootAuthority -Name FARMB -MetadataEndPoint https://farmb.foo.com/_layouts/15/metadata/json/1/rootcertificate

Now that we have our reference to the SPTrustedSecurityTokenIssuer for Farm B, which is in our variable $i, we can use that when granting rights to each of the realms we create. So to create the realms, we do this for each of the web applications:

#this first line only needs to be done once 

$realm = $i.NameId.Split("@")

 

#then do this for each web application

$s1 = Get-SPSite –Identity https://portal.foo.com
$sc1 = Get-SPServiceContext -Site $s1
Set-SPAuthenticationRealm -ServiceContext $sc1 -Realm $realm[1]
$p = Get-SPAppPrincipal -Site https://portal.foo.com -NameIdentifier $i.NameId
Set-SPAppPrincipalPermission -Site https://portal.foo.com -AppPrincipal $p -Scope SiteCollection -Right FullControl

Once you've completed this for https://teams.foo.com and https://my.foo.com, you will be able to issue queries from Farm B and get results from all of your content sources in Farm A. That includes your SharePoint content sources as well as non-SharePoint sources.