Create Sharing Link using CSOM/PnP.Framework

Brass Contributor

We have a requirement of having Unique/Durable link of sharepoint file, which will be stored in SQL DB by Job Scheduler (exe app). Documents might be moved to different folders within a site hence absolute URL cannot be trusted.
We have two options
1. Document ID service = Though its a good options, downside is, this service takes some time to generate Document ID (since timer job generates this)
2. Use Sharing option. We are exploring this option and came across this post where its answered how to generate sharing link from CSOM = https://docs.microsoft.com/en-us/answers/questions/84801/calling-the-sharelink-sharepoint-rest-api-e...

237286-image.png

 

We did try this code however we are always getting unauthorized. context object is generated from PnP. We need to use AppId and Secrete since its unattended scheduled job. Cred object is always showing null.. Any thoughts please?

Digest value and Web title are correct. However, Cleint.Upload call fails. (since Cred is blanks). Can app ID/Secrete not work with this?

 

 

 

using Microsoft.SharePoint.Client;
     using Newtonsoft.Json;
     using PnP.Framework;
     using System;
     using System.Net;
        
     namespace SP_ConsoleApp
     {
         class Program
         {
             static void Main(string[] args)
             {
                 string siteUrl = "https://dsds.sharepoint.com/sites/devstuff";
                 string clientId = "6ab77591-088a-447a-b406-23aadf9ae721";
                 string clientSecret = "afopU4VxvYDigYXW8K7tLOWONsdsdst9x3GFKOvr0Ng05lSM=";
        
        
        
                 //For SharePoint app only auth, the scope will be the SharePoint tenant name followed by /.default
                 var scopes = new string[] { "https://dsds.sharepoint.com/.default" };
        
                 using (var cc = new PnP.Framework.AuthenticationManager().GetACSAppOnlyContext(siteUrl, clientId, clientSecret))
                 {
                     cc.Load(cc.Web, p => p.Title);
                     cc.ExecuteQuery();
                     Console.WriteLine(cc.Web.Title);
        
                     var web = cc.Web;
                     var dig = cc.GetFormDigestDirect();
        
                     cc.Load(web);
                     cc.ExecuteQuery();
        
                     Console.WriteLine($"{web.Title}--{dig.DigestValue}");
        
                     ShareFile(cc, cc.Credentials as SharePointOnlineCredentials, dig.DigestValue);
                     Console.ReadKey();
                       
        
                 };
             }//main
             private static void ShareFile(ClientContext context, SharePointOnlineCredentials creds, string digest)
             {
                 try
                 {
                     string szRequestURL = @"https://dsds.sharepoint.com/sites/devstuff/_api/web/GetFileByUrl(@v)/ListItemAllFields/ShareLink?@v='/sites/devstuff/testLib/Document1.docx'";
        
                     string response = "";
                     using (var client = new WebClient())
                     {
                         client.Credentials = creds;
                         client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
                         client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
                         client.Headers.Add(HttpRequestHeader.Accept, "application/json;odata=verbose");
                         client.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0");
                         client.Headers.Add("X-RequestDigest", digest);
        
                         var endpointUri = new Uri(szRequestURL);
        
        
                         response = client.UploadString(szRequestURL, "{\"request\":{\"createLink\":true,\"settings\":{\"allowAnonymousAccess\":true,\"linkKind\":2,\"expiration\":null,\"restrictShareMembership\":false,\"updatePassword\":false,\"password\":\"\", \"description\":\"My description\", \"role\":8,\"applicationLink\":false,\"limitUseToApplication\":false}}}");
                         dynamic dynObj = JsonConvert.DeserializeObject(response);
                         if (dynObj == null)
                         {
                             return;
                         }
                         string szURL = dynObj.d.ShareLink.sharingLinkInfo.Url.Value;
                         Console.WriteLine("Sharing link: " + szURL);
                     }
                 }
                 catch (Exception e)
                 {
                     Console.WriteLine("Error sharing files: " + e.ToString());
                 }
             }
         }//cs
     }//ns

 

 

3 Replies

@Rohit Devmore 

 

Are you using SharePoint App Only Context? or are you using Azure AD App Permission to connect?

 

If you are using SharePoint App Only Context then you need to make sure two things

  • Make sure that you have "AllowAppOnlyPolicy" value to true while you have given permission via _layouts/appinv.aspx. If you are not suer about it then you can reassign permission in the site collection

 

<AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />
  </AppPermissionRequests>

 

  • Make sure that DisableCustomAppAuthentication is set to False in your Tenant (Important: Once you apply this change it can take maximum 24 hours to reflect). You can use Set-SPOTenant to do so.

 

If you are using Azure AD App Registration then make sure that you have given Application Level Permission in your App as shown in below

 

kalpeshvaghela_0-1662352378733.png

 

In case of Share Document code, Below is the sample where I am using Modern API to do so 

 

https://github.com/kavaghela/sharedocumentspapi

 


Hope it will helpful to you and if so then Please mark my response as Best Response & Like to help others in this community

 

 

 

Can you make sure that you have given correct permission in Azure AD App Registration? as you are using Client Id and Secret key you need to provide application permission.

 

 

@Rohit Devmore Refer similar thread of yours which might help you: Create Sharing Link using CSOM/PnP.Framework 


Please click Mark as Best Response & Like if my post helped you to solve your issue. This will help others to find the correct solution easily. It also closes the item. If the post was useful in other ways, please consider giving it Like.

Thank you Ganesh..Unfortunately all solutions are breaking inheritance. Might have to test our GraphAPI. Which means taking Infra teams help for assigning FIle.ReadWrite.all at tenant level. Hope there was better way