This project has moved. For the latest updates, please go here.

LDAPCP People Picker in SharePoint Multi Tenant

Feb 10, 2015 at 7:21 PM
Hi, We have installed SP 2013 in Multi Tenant mode according to Spence Harbar's excellent guides. We have now reconfigured to test ADFS as claims provider and of course People Picker stopped working. Installing LDAPCP worked fine and we now have the solution up and running. However, People Picker now returns users from the whole AD instead of only from the allocated tenant OU.

I'm speculating that standard People Picker in MT mode inspects the URL of the site that the user is in when the request is generated (HNSC) - then finds this URL in the Site Subscription properties (PS: Get-SPSiteSubscription) and finds the GUID for the tenant Subscription ID. From this one can find the OU which houses the tenants users (PS: Get-SPSiteSubscriptionConfig). From there the People Picker in MT mode defaults to restricting reults to those users in that OU.

Is this something that could be done by modifying the code in this Project? Is this something the authors would be interested in incorporating in the code base?

I'm hoping also to hear some suggestions as to how this could be achieved and any tips as to where to start.

Regards, Ulrik
Coordinator
Feb 12, 2015 at 11:50 AM
hello Ulrik,
I'm afraid this is not possible: when SharePoint calls a claims provider it provides a parameter called context that is normally the current URL.
unfortunately its value is not always accurate: claims providers are called at least 2 times to create a permission. The 1st time context value is current site collection/HNSC (which is fine), but the 2nd time it's always the root URL of the web application (in default zone).
Because of that you don't know from which site collection it is called.
This is something you can easily verify on your own if you download the package for developers and debug overriden method SetCustomConfiguration on any sample class: it is called at each request and contains parameter context sent by SharePoint.
Cheers,
Yvan
Feb 12, 2015 at 8:05 PM
Edited Feb 12, 2015 at 8:21 PM
We've been able to get this working in our environment.

Our multi-tenant (host header named) sites' People Pickers' are fully locked down.
We've had to make alterations to Yvand's main source code (v3.7) (not the developer package).

Results:
  1. Single SharePoint Farm
  2. http://tenant1.ourweb.com:80 (uses NTLM Authentication only); The people picker shows everything in the domain, but we do not allow our users to access the non-SSL encrypted site. It is inaccessible outside of our network. It is used for the Search Crawler only.
  3. The non-SSL site http://tenant1.ourweb.com was extended (to use it's own site in IIS) to:
    https://tenant1.ourweb.com:443 (SSL and uses ADFS Authentication only); the People Picker shows only ADFS (Users and Roles) who are members of Active Directory Group1, Group2, and Group3. The roles themselves also show up for selection in the People Picker. No other users or roles in the domain show up for selection in the People Picker even though other users and groups exist in the active directory domain.
  4. http://tenant2.ourweb.com:80 (uses NTLM Authentication only); The people picker shows everything in the domain, but we do not allow our users to access the non-SSL encrypted site. It is inaccessible outside of our network. It is used for the Search Crawler only.
  5. The non-SSL site http://tenant2.ourweb.com was extended (to use it's own site in IIS) to:
    https://tenant2.ourweb.com:443 (SSL and uses ADFS Authentication only); the People Picker shows only ADFS (Users and Roles) who are members of Active Directory Group1, Group5, Group6, and Group7. The roles themselves also show up for selection in the People Picker. No other users or roles in the domain show up for selection in the People Picker.
The key to this solution relies on the fact that each of our default zone root sites and internet zone root sites for each tenant have the same exact host header value... i.e. tenant1.ourweb.com... or tenant2.ourweb.com; the port numbers are just different (port 80 vs 443) between the zones.

I understand this solution uses a quite a bit of WFE memory on the server, but hey... it works. And it works well.

Now as for what you need to do in Yvand's main source code... I'll need permission from my company before I can release that info. I'll work on that.
Coordinator
Feb 13, 2015 at 8:20 AM
Hello,

Thank you for your input. I understand your implementation, but I tested again, and in FillResolve (SPClaim), SharePoint always passes the root URL of the web app (not the HNSC URL).
So I guess you workaround this by querying the whole AD in FillResolve (SPClaim)?

Based on this, wouldn't it be enough to just override SetCustomConfiguration method and implement this logic? It is called for each request and context parameter is passed.

Cheers,
Yvan
Feb 13, 2015 at 3:47 PM
I want to be clear on HNSC you have in mind.

I believe you are referring to a Web Application, lets say... https://tenant1.mysite.com that contains a "/sites/newSiteCollection1". ie.
https://tenant1.mysite.com/sites/newSiteCollection1 that has a host name of https://newSiteCollection1.mysite.com.... no, that will not work and I understand that.
The FillResolve will pass the root site URL which would be https://tenant1.mysite.com

But, your code only allows for a SINGLE LDAP query on the SharePoint Central Administration --> Security --> LDAPCP Configuration --> Global Configuration --> "Additional LDAP filter for user attributes" = some (&(!(disabled user = true)(OU=blah blah)(more filters WTF...)))

This setting allows for our own LDAP Query but it's applied to ALL Web Applications.
We need a separate LDAP query for each Web Application or (Tenant)!!!
And this LDAP setting only applies to Users... not Groups as well. Groups need to be included as well, or just let me put in my own full LDAP Query like the original People Picker has with the stsadm.exe command.

So, to get around this issue, we injected our business logic and wrapped the Add() function that is called inside the double nested loop. We basically use our business code to determine if the Add() should be allowed to be called or not based on the context URI passed in as a parameter in your function.
Apr 20, 2016 at 7:54 PM
Hi Yvand,

I can see that work has been progressing on the LDAP People picker since I was her last time :)

Is there any progress as far as using this in our Multi-tenant scenario? We are now designing our SharePoint 2016 MT system.

Cheers,
Ulrik
Coordinator
Apr 26, 2016 at 11:36 AM
Hello Ulrik,
currently it's still not possible to customize LDAP filter based on the current context (web application).
Would that help if it was possible in next version through custom code only (by inheriting LDAPCP class)?
Note that the main drawback is that you won't be able to use LDAPCP administration pages
thanks,
Yvan
Apr 26, 2016 at 6:25 PM
Hi Yvand,

Thank you very much for getting back to me. SharePoint in Multi Tenant mode is basically the standard release code base but doeing a scripted install and using the -partitionmode flag to enable data partitioning. The Subscription Service then allocates a unique GUID for each subscription. All data belonging to the tenant is then tagged with the Subscription ID.

Here is a quick overview: https://technet.microsoft.com/en-us/library/dn659287.aspx

We are in fact running all tenants under a single Webapp - for each Tenant/subscription we then configure people picker to restrict the search scope to the tenant OU:

We configure this using the Set-SPSiteSubscriptionConfig cmdlet with the -UserAccountDirectoryPath https://technet.microsoft.com/en-us/library/ff607622.aspx

So while running under Negotiate auth People Picker will aerch only its own OU.

This behaviour breaks for the built in people picker when the farm is configured to use ADFS auth.

Ideally we could therefore have situation where ldapcp identifies which SIte is calling the People picker, this site will have the SubscriptionID property as a GUID (always). This sub ID has a property UserAccountDirectoryPath which could then be used to restrict the search.

I don't know if any of this makes sense, however, I must admit that we have not done any recent testing of this either for built-in people picker or for ldapcp.

We will be moving forward with a Multi tenant test install of SP 2016 as soon as it's RTM code is available. That install will be configured for ADFS auth (token based)

If you could indicate if my idea of using the SubscriptionID info to restrict search could be within the scope of ldapcp. I could then have our own development team look at it.

Be hearing from you
Coordinator
Apr 27, 2016 at 11:29 AM
Hello,

ok, I understand your scenario, but I cannot say if LDAPCP would be capable of this because I don't have such setup.
But this is something you can check on your side: basically, what matters is the value of parameter "context" that SharePoint passes to methods FillSearch and FillResolve: it contains the URL and this is the only thing LDAPCP may use to apply a filter based on your needs.

So you can check the value of parameter "context" in different tenants and confirm if it contains the URL of the tenant.
Unfortunately you can't check it with LDAPCP directly, but a simple way is to create a custom claims provider that inherits LDAPCP and overrides method SetCustomConfiguration (that gets the context too).
You can find example of this if you download "LDAPCP for Developers".

Thanks,
Yvan

As a side note, it's especially important to check the value of parameter "context" when it's called from FillSearch(...SPClaim...) method, as it can be different from other methods.