External sharing API for SharePoint and OneDrive for Business

Office365PnPLogoRed_thumb1One of the really nice capabilities in the Office 365 is the external sharing, which enables you easy way to share sites and documents also with people who are not necessarily part of your own organization. From UI capability perspective this capability has been in the service already quite a while and it’s nicely explained on one of the blog posts at Office blogs.

With external sharing you can enable multiple different business scenarios, like following:

  • Use Office 365 as your extranet platform by sharing sites between your business partners
  • Share individual documents from SharePoint site or OneDrive for Business service cross known people
  • Share files with either view or edit permissions with anonymous links – no need for actual authentication

There has been pretty constant ask from community to make this capability to work with APIs as well and we actually released API level support for this capability already spring 2015. Since the API documentation did not however existed and there was no samples actually using the code, this capability has not really been used. In this blog post we’ll have a closer look on these APIs and we provide fully functional sample for you to start using these APIs within your deployments.

Notice that even though this blog post concentrates on the CSOM API, these same capabilities are also available with REST interfaces.

External sharing API documentation at MSDN

MSDN documentation is not unfortunately quite up to date related on following methods, but we are working on getting it updated accordingly. Before those updates, you can find needed guidance from below chapters. I would actually recommend using the extensions methods from the PnP Core component or from this sample for simplifying the operations, since these sharing methods are not as easily usable due specific strings to be included in the sent information.

Web.ShareObject method

This is the main method for sharing document or site with external people.

 public static SharingResult ShareObject(
     ClientRuntimeContext context,
     string url,
     string peoplePickerInput,
     string roleValue,
     int groupId,
     bool propagateAcl,
     bool sendEmail,
     bool includeAnonymousLinkInEmail,
     string emailSubject,
     string emailBody
 )

Parameters

  • url
    Type: System.String Full URL of the web or a document to be shared. “http://contoso.sharepoint.com/sites/extranet1” –  for document sharing ”https://contoso.sharepoint.com/sites/extranet1/shared%20documents/mydoc.xlsx” – for document sharing  
  • peoplePickerInput
    Type: System.String A string of JSON formatted data representing users in people picker format. This is pretty hard requirement, since people picker format is not actually documented. Luckily we can use ClientPeoplePickerWebServiceInterface.ClientPeoplePickerResolveUser() for resolving this string for us in right format. Example entry: “ [{"Key" : "i:0#.f|membership|vesaj_vesajsep2015.onmicrosoft.com#ext#@veskuonline.com", "Description" : "vesaj_vesajsep2015.onmicrosoft.com#EXT#@veskuonline.com", "DisplayText" : "Vesa Juvonen", "EntityType" : "User", "ProviderDisplayName" : "Tenant", "ProviderName" : "Tenant", "IsResolved" : true, "EntityData" : {"MobilePhone" : "", "Email" : "vesaj@vesajsep2015.onmicrosoft.com", "Department" : "", "Title" : "vesaj@vesajsep2015.onmicrosoft.com", "PrincipalType" : "GUEST_USER"}, "MultipleMatches" : []}] ”  
  • roleValue
    Type: System.String The sharing role value for the type of permission to grant on the object. There are few different options for this dependent on the sharing style. If you share a document you will need to use either of following values: "role:1073741827" ”role:1073741826” When you are however sharing a site for external user, you’ll need to use following format: ”group:{groupId} ” – {groupId} should be replaced with the unique group id from the site where external user will be assigned to.  
  • groupId
    Type: System.Int32 The ID of the group to be added to. Use zero if not adding to a permissions group. Not actually used by the code even when user is added to existing group. See description for roleValue.  
  • propagateAcl
    Type: System.Boolean A flag to determine if permissions should be pushed to items with unique permissions.  
  • sendEmail
    Type: System.Boolean Flag to determine if an e-mail notification should to sent, if e-mail is configured.  
  • includeAnonymousLinkInEmail
    Type: System.Boolean If an e-mail is being sent, this determines if an anonymous link should be added to the message.  
  • emailSubject
    Type: System.String Text for the subject line of the e-mail – which is however always ignored in the sent emails around sharing of sites or documents.  

Example execution of above method.

 // Do your stuff
 string url = "https://contoso.sharepoint.com/sites/extranet2";
 string roleValue = "group:8"; // int depends on the group IDs at site
 int groupId = 0;
 bool propageAcl = false; // Not relevant for external accounts
 bool sendEmail = true;
 bool includedAnonymousLinkInEmail = false;
 string emailSubject = null;
 string emailBody = "Site shared";
 SharingResult result = Web.ShareObject(ctx, url, peoplePickerValue,
                                 roleValue, groupId, propageAcl,
                                 sendEmail, includedAnonymousLinkInEmail, 
                                 emailSubject, emailBody);
 ctx.Load(result);
 ctx.ExecuteQuery();

Other sharing methods available in CSOM or REST

Here’s the other methods around external sharing capabilities at the MSDN.

  • Web.CreateAnonymousLink

    • Notice that you do not need to create as cryptic URL as mentioned in the MSDN documentation. Simple URL pointing directly to file works as well.
  • Web.CreateAnonymousLinkWithExpiration

    • Same as for above, the requirement for URL format is wrong in the current documentation.
  • Web.UnshareObject

    • Documentation is pretty accurate, but is missing full example on the use case

 

External sharing extension methods

We created a new reference implementation of the sharing capabilities in Office 365 Developer Patterns and Practice guidance with name of Core.ExternalSharing. This is isolated sample, which demonstrates usage of above methods in practice. Since default methods are however pretty cryptic, sample is using more straight forward methods as wrappers for the actual CSOM methods. This is implemented with extension methods, which can be easily taken into use from any other solution. These extension methods are also on the PnP Core component as part of the October 2015 release, so that you can easily take advantage them together with other operations from PnP Core component.

How to get started with the extensions methods? – Add reference to PnP Core Component or copy the extension methods from PnP reference solution. Add using statement for Microsoft.SharePoint.Client and you’ll get following methods automatically available from the Web object. If you’d like to implement these by yourself, you can use the PnP reference sample to figure out the needed values for external sharing APIs.

ShareSite

Can be easily used to share a site for given email address. Supports providing either view, edit or owner permissions, which are resolved to default permissions groups associated to the site.

 // Share a site for the given email address
 SharingResult result = ctx.Web.ShareSite("Someone@example.com", 
                         ExternalSharingSiteOption.Edit,
                         true, "Here's a site shared for you.");

ShareDocument

Can be easily used to share a document for given email address. Supports providing either view or edit permission to the document.

 // Share document for given email address
 SharingResult result = ctx.Web.ShareDocument(
                      "https://contoso.sharepoint.com/docs/sample.doc", 
                      "someone@example.com", 
                      ExternalSharingDocumentOption.Edit,
                      true, "Here's your important document");

CreateAnonymousLinkForDocument

Can be easily used to get anonymous link to given document with either view or edit permissions. Users with this link do not have to sign-in for accessing the document.

 // Create anonymous link for document
 string link = ctx.Web.CreateAnonymousLinkForDocument(
                  "https://contoso.sharepoint.com/docs/sample.doc",
                  ExternalSharingDocumentOption.View);

CreateAnonymousLinkWithExpirationForDocument

Can be used to get anonymous link with automatic expiration on provided date and time. Users with this link do not have to sign-in for accessing the document. In below example usage, we will add automatic expiration for this link in next 7 days.

 // Create anonymous link with expiration for document
 string link = ctx.Web.CreateAnonymousLinkWithExpirationForDocument(
                  "https://contoso.sharepoint.com/docs/sample.doc",
                  ExternalSharingDocumentOption.Edit,
                  DateTime.Now.AddDays(7));

 

Provided sample solution

Provided sample solution which is part of the PnP material can be considered as a “stepping stones” sample and it only concentrates on demonstrating the different aspects of the external sharing without fancy UIs, so that you can easily adapt the API usage in your deployments. Here’s few UIs of the sample solution, but we are not going to cover this one too detailed in this blog post.

This sample concentrates on demonstrating following aspects

  1. Enable external sharing at tenant and site collection level
  2. Share a site for external users
  3. Share documents for external users, including options for anonymous links

See PnP documentation around this reference sample for more information.

sitecolsettingssitesharing

documentSharing

FAQ

Q - Does these sharing APIs work with app/add-in only permissions?

A - Yes

Q - Does this work for files in OneDrive for Business?

A - Yes. APIs are working with documents from OneDrive for Business sites or with SharePoint sites and documents.

Q - Do I need to get app/add-in installed on site to use this?

A - No. Sample is using provider hosted add-in UI just for demonstration purposes, you can use Azure WebJobs or whatever model for running the managed code demonstrated in the sample.

Q - Do I need to use app/add-in authentication for this?

A - No. You can use classic account and pwd model with SharePointOnlineCredentials for making this work.

Q - I can't make the API to work within file or site level - what's wrong?

A - Typical issue would be tenant or site collection level settings. Ensure that you have external sharing enabled at both tenant and in the specific site collection level. You can use this sample app/add-in to access that information or alternatively use tenant SharePoint admin UIs for those configurations.

Q - This app/add-in is requesting farm permissions, can't I make any of this work with smaller permissions?

A - You can. Add-in is also accessing farm level settings for the tenant management, which is the reason for so high permissions. If you are only sharing sites or documents, you will need lower permissions depending on exact case. For site level sharing, you'll need to request Site Collection Owner permissions and for document sharing you'll need site manage permission.

Q - What if I try to share a site or document with insufficient permissions?

A - You will get AccessRequestsQueued as the return value for the sharing request, which means that your request is queued for the site owner for verification. This is similar behavior as with the UI based sharing using browser. See below picture for the entry added in the queue for site owner processing.

Office 365 Developer Patterns and Practices

Office365PnPLogoRed_thumb1Techniques showed in this blog post are part of the Core.ExternalSharing solution in the Office 365 Developer Patterns and Practices (PnP) guidance (Oct 2015 release), which contains more than 100 samples and solutions demonstrating different patterns and practices on the SharePoint add-in model development, Office 365 APIs and other development models with Office 365 and SharePoint.

Get latest news around the PnP guidance from https://aka.ms/OfficeDevPnP. Please join us on sharing patterns and practices for the community for the benefit of the community. If you have any questions, comments or feedback related on this sample, blog post or anything on PnP, please use the PnP Yammer group at https://aka.ms/OfficeDevPnPYammer.

“From the community for the community” – “Sharing is caring”