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. “https://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”

Comments

  • Anonymous
    December 08, 2015
    Hi Vesa, Hope you are doing well! As you know, Microsoft improved the Share function to generate two more links for company member, one is edit link, another is view link, the company member can access the document with the two links even he doesn't have enough permission. Do you know how to get the two links by CSOM? Thank you. Best Regards, Long

  • Anonymous
    December 22, 2015
    Hi Long Liang, that would be the method in the Web object called CreateAnonymousLink. See following for additional details: msdn.microsoft.com/.../microsoft.sharepoint.client.web.createanonymouslink.aspx

  • Anonymous
    December 31, 2015
    Hi Vesa, I tried you code and external sharing works. When i share an item with an external user it send an email to external user to accept the invitation. But im getting an error when an item that resided in sharepoint Add-In web is shared with a external user. When the external user tries to accept the invitation he get the following error "/sites/site Name/Add-In Name/_layouts/15/acceptinvite.aspx is not accessible in the context of a SharePoint App." **This happens only for Add-in web elements and when some thing is shared with the external user for the 1st time. if some thing was shared with the external user previously above error doesn't come. Any idea why this is happening? i posted a question as wel social.msdn.microsoft.com/.../accepting-external-sharing-invitations-fails-for-sharepoint-addin-elements thanks :)

  • Anonymous
    January 03, 2016
    Hi Pubudu, External sharing was never intended to be used within add-in web, so it's designed to be used in normal SharePoint sites. This means that I'm not surprised that you might be facing some issues with this and there's random exceptions.

  • Anonymous
    March 04, 2016
    Hello: If I wanted to add a user to the Web via the Sharing API and NOT send the email but somehow wanted to accept the user to the site so that the user can log in - is it possible? I've been digging and cannot seem to find anything on it. Thanks!

  • Anonymous
    July 08, 2016
    Hey Vesa, would you happen to know if there is a way to get the "shared" property of a file?

  • Anonymous
    January 04, 2018
    Hi VesaCan I check if a file already has an anonymous link?Kind regardsThomas

  • Anonymous
    December 31, 2018
    (The content was deleted per user request)

  • Anonymous
    December 31, 2018
    @Vesa - I am having trouble getting a Rest API call to CreateAnonymousLinkForDocument working in Postman with a relevant bearer token value. All the successful examples I can find are including the X-RequestDigest, but based on your first FAQ above - I don't think that should be necessary? Unless I am misunderstanding your explanation of the functionality. I am writing a B2B web api proxy, so I won't have a user context to draw from. Here is a post detailing my problem. https://sharepoint.stackexchange.com/questions/254950/sharepoint-createanonymouslink-with-rest-api-in-postman

  • Anonymous
    May 23, 2019
    Is there a way to share a folder with an external user such that only an access code is required?I've raised a more detailed question on StackOverflow https://stackoverflow.com/questions/56279481/how-to-share-a-sharepoint-folder-with-an-external-user-without-requiring-a-micro