Welcome to my blog, stay tunned :
Home | Blogs | Stephane Eyskens's blog

Office 365 & SharePoint Online - Control sharing with External Users, uggly but effective workaround

Hi,

At the time of writing, Office 365 is a great solution that is ready to use and usually a perfect platform for small to mid-sized enterprises having not too many constraints regarding data confidentiality, data sharing etc..For larger enterprises or "sector senstiive" (bank, pharma...), things can be a little more challenging when it comes to collaboration with external partners.
As of now, the only way to collaborate with partners in 365 is to enable external sharing. However, external sharing is often seen as a problem by sensitive companies because:

  • It allows people to share a site/document with ANYONE in the world
  • There is no garantee that the person who receives the invitation link is well the one who will accept it. If the mail gets intercepted or forwarded to anyone else, anyone with either a Microsoft account, either an Organizational account can accept the invitation and have access to potentially sensitive documents

In other words, you cannot restrict external sharing to specific partners only. It would be great if Microsoft could come with the following extra options:

  • Offer an option to limit sharing with Organizational accounts only. This would not protect against the mail issue but would at least ensure that people you invite have at least a tenant and not anyone in the world with a Microsoft Account (or who could create one on the fly). It'd be better than nothing
  • A better option would be : limit the domains users are allowed to send invitations to. This is the workaround I'll explain a bit later. That would still not protect against the mail issue but would at least prevent users from sharing with anyone.

Before jumping into that workaround, let's see what else me and others have tried

  • http://blog.atwork.at/post/2014/12/06/How-to-use-external-users-in-Share.... Here the key is to use another AAD to create external users. The problems I see with this approach : 1) people can still invite anyone, they're not restricted to sharing only with users from that AD. 2) Invited people have another set of credentials to remember and cannot use their own credentials (either Organizational, either Microsoft account)
  • I tried to dig the GRAPH API to add external users to the Office 365 AAD. It works but...it seems that external users created by SharePoint Online are flagged differently. When a person accepts an invitation, SharePoint Online creates a new user (if necessary) in the Office 365 AAD. You can easily recognize them if you go to 365's admin portal and list users. You'll recognize external users because they have a "#-EXT-#" in their UPN. If you click one of those, you won't be able to change anything, options are grayed out and 365 tells you explicitely that you can't change them. When an external user is created in the 365 AAD with the GRAPH API or with the Management Portal, you also see the "-#ext#-" thing in the UPN but you are allowed to assign them licenses etc..This clearly means that they are not truely considered external...altough it i's indicated in their UPN.

The interesting bits I found out is that if you add a Microsofft Account in the 365 AAD via the Azure Management Portal, a corresponding #ext# user shows up in the 365 admin portal but if you then grant that account to access a SharePoint site, the owner of the Microsoft account cannot log in using his credentials. The management portal (as well as the graph API) actually creates another user and you can only login using 365 credentials...although the account shows up as "Microsoft Account" in Azure. This is quite funny to see! So, what's the point of adding Microsoft Accounts to 365 AAD if they cannot login using with their account? Well, I found out that if you bind an Azure web site (or onprem web site) with the 365 AAD for authentication, people will be able to login with their Microsoft Account to your web site but not to SharePoint Online. This clearly means that the only way to have a true external user is SharePoint Online is to let it send an invite and go through its special way of adding users.

I thought : ok no problem, let's see if CSOM allows to share programmatically...no luck! That's where you start thinking workarounds.

Workaround #1

That workaround isn't dirty but can be tedious for end users. A way to mitigate the "share with anyone issue" could be to create a custom permission level you'd call "Business Owners" that doesn't include the "Manage Permissions" permission. That will prevent people from sharing with external users. So, sharing would be made possible only for allowed users (full control/site col admins). This is absolutely clean but it means that you need to put a "request process" in place so that whenever users want to share with external users, they need to ask it to someone with the proper permissions. It works but can be tedious and slow down (if not kill) the user adoption.

Workaround #2

Here comes the dirty workaround. I tested it and it works fine! If you provision your 365 collaboration sites automatically (which is our case), you could provision this:

  • A list with unique permissions (read for everyone), write only for site collection administrators providing you don't set business users site collection administrators
  • That list would contain the allowed domains users could send invitations to

This per site collection approach allows you to envision a "one collaobration site per partner" strategy and have a more granular way of allowing domains. If on the contrary, you want to allow all your collaboration sites to invite the same domains, you could provision this list in the root site collection of the collaboration web application.

One row per allowed domain. Ok fine but what can we do with this list now? Well, the idea is to tweak the sharing page. Whatever you share (site, document), SharePoint will always redirect you to the /dev/_layouts/15/aclinv.aspx page. The idea is to inject a javascript routine that will do the following:

  • Disable the Share button
  • Load the allowed domains via a REST API call in JavaScript
  • Add a FocusOut event to the People Picker control
  • Check the resolved entities and see if their domain matches any of the allowed domain list
  • Adjust the Share button availability accordingly

This is what it looks like in pictures:












Why is it uggly? Well, because somehow "securing/controlling" something in JavaScript is never a good idea but remember, at the time of writing there is NO WAY to send invites programmatically via CSOM/REST/whatever. So, could users workaround the workaround to still be able to inivite anyone? Hell no!

So, what could they try to prevent this control from happening? Disable javascript in their browser? Well: try it and SharePoint will likely be unusable!

Last but not least, you'll need to provision a custom action of type scriptlink at site collection level to inject your script in every page.


Happy Coding

Comments

Workaround 2

HI Stephan,

You seem to have tested the work around 2 and got it working, would you mind sharing the code here please?

Cheers,
Manu

Re: Workaround 2

I'm not sure if we can achieve the workaround #2 because when you click Share button in SP Online it opens a popup and I'm not sure if we can load custom js in modal popups?

Has anyone achieved what the author proposes as workaround 2 here?

Adding external users with the API

Hi,
How did you create external users with the Graph API, everywhere I look it says that this is not possible!
Thx

External users

Hi,

I think that I was just explicitely adding the #ext# stuff in the login name but I don't have the code right now! Anyway, this post is outdated since you can now do it out of the box https://blog.onedrive.com/wp-content/uploads/2015/09/ODB_Extending_Our_I...

Best Regards

Can't find the option you have on screenshot

Can't find the option you have on screenshot.

External sharing

It's not yet rolled out but it's coming so you'd better not plan to build anything special, just be a bit patient

Read Only Sharing

Anyway to default sharing to read only?

Currently seems to be an additional manual step which users forget!

Read-Only Sharing

Well, if it was possible to share a site via CSOM, then you could just restrict users from sharing and just make share requests, then, after some kind of business logic validation, you could share and give read/write permissions to the partner. However, if you really want to restrict to "read-only", I guess the only option available for now is to restrict end users permissions so that they can't share with external users at all. In parallel, you could have a manual request process in place but this is quite tedious for both end users and admins.

Hi, a quick note about

Hi, a quick note about security. You admit that JavaScript isn't a 'best practice' to secure/controle, but since it's the only option I'd have chosen the same. I do however want to add a note on the possibility of a user workaround. The user can't (indeed) prevent te script from loading since it's either all javascripts or none - and the latter isn't really an option. The user could however simply enable the share button or trigger form submit using a simple javascript/jquery command on the developer console.

Security

Hi,

Indeed, that's a very valid point and that's why indeed JavaScript is never a good idea :). The only ideal solution would be an out of the box one but with this workaround you'll cover the "normal" user scenario.

Best Regards