Introduction

Azure Functions provides a powerful mechanism for executing serverless code triggered by events. When working with SharePoint, Azure Functions can interact with SharePoint Online in many ways. One such secure way for authentication is with the self-signed certificate for app-only authentication. This article will walk you through the steps for using Azure Function to access SharePoint data using a self-signed certificate.

Step-by-step guide

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PnP.Core.Auth;
using System.Security.Cryptography.X509Certificates;

[assembly: FunctionsStartup(typeof(CRUDOperations.Startup))]

namespace CRUDOperations
{
    class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var config = builder.GetContext().Configuration;
            var azureFunctionSettings = new AzureFunctionSettings();
            config.Bind(azureFunctionSettings);

            builder.Services.AddPnPCore(options =>
            {
                options.DisableTelemetry = true;

                var authProvider = new X509CertificateAuthenticationProvider(
                    azureFunctionSettings.ClientId,
                    azureFunctionSettings.TenantId,
                    StoreName.My,
                    StoreLocation.CurrentUser,
                    azureFunctionSettings.CertificateThumbprint);

                options.DefaultAuthenticationProvider = authProvider;

                options.Sites.Add("Default", new PnP.Core.Services.Builder.Configuration.PnPCoreSiteOptions
                {
                    SiteUrl = azureFunctionSettings.SiteUrl,
                    AuthenticationProvider = authProvider
                });
            });
        }
    }
}

Now create a class named AzureFunctionSettings.cs class, This class will map the configuration settings from local.settings.json.

Replace the below code in the AzureFunctions.cs file.

namespace CRUDOperations
{
    public class AzureFunctionSettings
    {
        public string SiteUrl { get; set; }
        public string TenantId { get; set; }
        public string ClientId { get; set; }
        public string CertificateThumbprint { get; set; }
    }
}

Now in Your Function1.cs file replace the below code.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using PnP.Core.Services;
using System.Linq;
using PnP.Core.QueryModel;

namespace CRUDOperations
{
    public class GetSharePointListData
    {
        private readonly IPnPContextFactory pnpContextFactory;

        public GetSharePointListData(IPnPContextFactory pnpContextFactory)
        {
            this.pnpContextFactory = pnpContextFactory;
        }

        [FunctionName("GetSharePointListData")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("Fetching data from the SharePoint list.");

            try
            {
                using var pnpContext = await pnpContextFactory.CreateAsync("Default");
                var list = await pnpContext.Web.Lists.GetByTitleAsync("ForEx Rates using API");
                var items = await list.Items.ToListAsync();

                var data = items.Select(item => new
                {
                    Id = item.Id,
                    Date = item["Date"],
                    BaseCurrency = item["BaseCurrency"],
                    Rupees = item["ComparedtoRupees"],
                    Euro = item["ComparedtoDoller"],
                    BritishPound = item["BritishPound"],
                    KuwaitiDinar = item["KuwaitiDinar"],
                    SwissFranc = item["SwissFranc"]
                }).ToList();

                return new OkObjectResult(data);
            }
            catch (Exception ex)
            {
                log.LogError($"Error: {ex.Message}");
                return new StatusCodeResult(500);
            }
        }
    }
}

In the above code make sure to change the List name with your list name. In my case I am using the "Forex Rates using API" list from my SharePoint site.

In the function, data is mapped to a custom object using item["FieldName"], where FieldName matches the internal names of your list columns. The properties in the object should align with your list fields to ensure accurate mapping. Update these fields based on your SharePoint list's structure.

Now Save all the files and run the project.

The below window will appear.

Project

Now Hover on the URL, press Ctrl then click on the URL.

The browser will open and data will be displayed.

URL