Calling SharePoint CSOM from Azure Functions (Part 3)

Now that a skeleton the Azure function is written and registered in Azure Active Directory, it’s time to add code to call the SharePoint Online Client-Side Object Model (CSOM). Much of CSOM is generated from SharePoint’s server-side API, making it by far the most complete API for SharePoint Online.

In this article you will complete a simple example of calling CSOM from an Azure Function. The completed code is in a gist here.


This series will show you how to call SharePoint’s Client-Side Object
Model (CSOM) from an Azure Function. It’s divided into three sections,
in hopes that the first two sections are reusable in other scenarios. I’ll probably add more scenarios in the future, but will keep the URL’s the same.

Part 1 – Setting up your Azure Function
Part 2 – Registering your Azure Function with Azure Active Directory
Part 3 – Calling CSOM with Application credentials from your Azure Function (this posting)


Return to the Azure Function you created in Part 1 of this series; the CSOM code will be added to this. To use the CSOM, we need to reference two .NET assemblies: the CSOM, of course, and the Azure AD Authentication Library (ADAL) to provide authentication. To add the reference from the web browser, open the View Files tab on the right and click + to add a new file called project.json.

AZF-CSOM-01.png

Fill it in with the following JSON:

{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.IdentityModel.Clients.ActiveDirectory" : "3.13.7",
"Microsoft.SharePointOnline.CSOM": "16.1.5813.1200"
}
}
}
}

This will tell Azure to load up these two nuget packages and reference them from your Azure function.

Next, on that same View Files tab, upload your .pfx certificate file.

Next, create a new file called csomHelper.csx. We’ll hide the details of authenticating to SharePoint in this class.

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.SharePoint.Client;
using System.Security.Cryptography.X509Certificates;

public static class csomHelper {

private static string ClientId = "(Application ID)";
 private static string Cert = "(filename).pfx";
 private static string CertPassword = "(password)";
 private static string Authority = "https://login.windows.net/(tenantName).onmicrosoft.com/";
 private static string Resource = "https://(tenantName).sharepoint.com/";

public async static Task<ClientContext> GetClientContext(string siteUrl)
 {
 var authenticationContext = new AuthenticationContext(Authority, false);

var certPath = Path.Combine(Environment.GetEnvironmentVariable("HOME"), "site\\wwwroot\\&lt;FunctionName&gt;\\", Cert);
 var cert = new X509Certificate2(System.IO.File.ReadAllBytes(certPath),
 CertPassword,
 X509KeyStorageFlags.Exportable |
 X509KeyStorageFlags.MachineKeySet |
 X509KeyStorageFlags.PersistKeySet);

var authenticationResult = await authenticationContext.AcquireTokenAsync(Resource, new ClientAssertionCertificate(ClientId, cert));
 var token = authenticationResult.AccessToken;

var ctx = new ClientContext(siteUrl);
 ctx.ExecutingWebRequest += (s, e) =>
 {
 e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + authenticationResult.AccessToken;
 };

return ctx;
 }
}

Copy the Application ID from the Azure application registration screen in as the ClientId. You also need to include the certificate file name and password, and to plug in your tenant name to get the right login and resource URL.

Line 17 opens the certificate file; line 24 uses the cert to initiate an authentication flow to SharePoint. If this works, the application receives an access token that it can use to access SharePoint. Lines 27-31 hook up an event handler which will run whenever CSOM executes a request; it will insert the access token into the HTTP header so the request is authorized by SharePoint. The resulting client context is now logged in and ready to use.

Next, return to the run.csx file and fill in the calls to CSOM. At the top, load the CSOM helper class and add using statements for the CSOM.


#load "csomHelper.csx"

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;

Now insert the following code into run.csx just before the return statement; it will look up the WOPI URL for the document at the siteUrl and path that were passed into the Azure function.


// Get Office Online (WOPI) URL
using (var ctx = await csomHelper.GetClientContext(siteUrl))
{
ClientResult<string> result;

File f = ctx.Web.GetFileByServerRelativeUrl (itemUri.PathAndQuery);
result = f.ListItemAllFields.GetWOPIFrameUrl(SPWOPIFrameAction.View);

ctx.Load(f.ListItemAllFields);
ctx.ExecuteQuery();

itemUri = new Uri(result.Value);
}

Test your function on the test tab on the left (make sure the siteURL and path point to a Word, Excel, or PowerPoint file in SharePoint ONline). The result should be the WOPI URL of the document.

AZF-CSOM-03.png

Paste the URL into a browser and see if it works!

AZF-CSOM-04.png

From here, you can do anything you need to using CSOM, subject to the permissions you granted the Azure Function application. The completed code is here so you don’t have to piece it together from this article.

Thanks for reading, and please send feedback in the comments!

17 thoughts on “Calling SharePoint CSOM from Azure Functions (Part 3)

    1. No it’s not the only option; you can use a username/password to spin up the CSOM ClientContext. However – if it’s an actual user, and he or she leaves the company or changes password, the code breaks. If it’s not an actual user, you’re buying a license so the “service account” can access SharePoint. The certificate avoids those problems, and also has limited access (whereas the username/password allows anyone to access Exchange, Skype, etc – everything in O365!)

      Like

  1. Thank you, that was a very illuminating article. End-to-end rather than snippets, which is great.

    I leveraged the article and tried to do the same with a app registration key secret only, rather than certificates, but failed. Couldn’t get a authenticationContext.AcquireTokenAsync method to play ball.

    It was probably me, but before I thrash away at it some more, should it be do-able? That is: Using a key secret only from the app registration, rather than certificates, and the right AcquireTokenAsync method? Or am I barking up the wrong tree and wasting my time?

    Like

      1. Thanks for the articles, very helpful. I finally got a sample working with azure app using MSI to retrieve certificate from azure key vault and then access csom. Regarding the 401 errors, I tried to get it working using key only (no certificate) but failed with 401 unauthorized. Then I found this page which at the very bottom in FAQ section states that app only auth to sharepoint online is only supported with certificates and all other methods (ie app id/key) will fail. Hopefully will help save some time for others:

        Can I use other means besides certificates for realizing app-only access for my Azure AD app?
        No, all other options are blocked by SharePoint Online and will result in an Access Denied message.

        https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread

        Liked by 1 person

  2. I’ve done all of your steps , but when I want to test it I’m getting this error :
    “Exception while executing function: CheckUserInGroups -> The remote server returned an error: (401) Unauthorized.

    Liked by 1 person

  3. did I lose something or should we “somehow” declare the function in Sharepoint as well? How else would Sharepoint know the permission of this funapp (if any). Or is it enough to register this in azure? I have something in mind as trusting the sharepoint add in.

    Liked by 1 person

    1. You don’t have to give it permission in SharePoint, you grant the permission in Azure AD. There are 2 kinds of permission in there: App permissions (which act as the app itself) and Delegated permissions (which act on behalf of a user, but the user isn’t logged in here so you can’t use those). So, in Azure AD you need to grant permission to Office 365 SharePoint Online and choose one or more of the Application Permissions based on your need. These permissions apply to every site collection! So do guard your app secret carefully!

      Liked by 2 people

  4. Hi Bob,

    Great article, really helped me. I was wondering what your thoughts are on security aspect f this approach. While adding username and password in the function app is unsecure, do you think uploading the private key and its password can be a bit unsecure as well? In theory anyone with access to the portal can look at the pfx file and its password.

    Thanks,
    Nishant

    Liked by 2 people

Leave a comment