Azure Web App authenticating to SharePoint with an App Registration and Certificate

The goal of this post is to explain (to my future self) how to create an ASP.NET C# application that uses an Azure App Registration configured with a Certificate to access a SharePoint site.

The advantage to this approach is that your application can be granted permissions to SharePoint, Microsoft Graph, and other services using the App Registration rather than a specific user account.

My application is ASP.NET V4.8 that is published to an Azure Web App. It talks to SharePoint to do various things and needs to be able to authenticate.

Here are the main things I will cover.

  1. Create a Self-Signed Certificate.
  2. Create an App Registration.
  3. Prepare the Azure Web App.
  4. Authenticate with the App Registration.

Step 1: Create a Self-Signed Certificate.

I have another post that explains how to Create a self-signed Certificate using PowerShell.

Step 2: Create an App Registration.

I have another post that explains Azure App Registration for Select SharePoint Sites.

Step 3: Prepare the Azure Web App.

If you’re not using an Azure Web App, you can skip this step.

A couple of things will need to be configured in your Azure Web App.

Step 3a: Add your Certificate to the Azure Web App. Since we’re deploying our code to run in an Azure Web App, we require a place to store the Certificate we created in Step 1.

  1. Open your Web App, then, click Certificates on the left navigation.
  2. Select Bring your own certificates (.pfx) tab.
  3. Upload the .pfx file that was created in Step 1.
  4. Enter your .pfx password during the upload.
  5. Copy the Thumbprint that is shown after the upload is complete.

Step 3b: Azure Web App Environment Variables. Next, we need to configure the Web App to look for the certificate.

  1. Open your Web App, then, click Environment Variables in the left navigation.
  2. Add a new App Settings variable.
  3. Name the variable WEBSITE_LOAD_CERTIFICATES. This needs to be exact.
  4. Set the value of the variable to your Thumbprint you copied in step 3a.
  5. Save.

If you want to debug locally, you will also have to add your .pfx file to your local certificate store. Search for Manage User Certificates on your Windows machine, then add the .pfx (not the .cer file!) to your Personal Certificates. The GetCertificates function should retrieve your certificate locally, and the same code will retrieve it from your Web App when deployed.

Step 3c: Add your remaining App Settings I’m also adding some other App Settings that I’ll need. These same settings should be added to your web.config file in the appSettings section. When running locally, your web.config is used, when running in the Web App, your App Settings will be used.

  • SharePointSiteUrl: The URL to our SharePoint site.
  • AppId: The GUID found on your App Registration overview page.
  • TenantId: Another GUID found on your App Registration overview page.
  • RedirectUrl: Whatever redirect URL you may need. Mine is https://localhost.
  • WEBSITE_LOAD_CERTIFICATES: This is the App Setting added in the previous step. It is the Thumbnail ID for your Certificate.

Step 4: Authenticate with the App Registration.

Next, let’s write some code!

Add these packages to my project in Visual Studio:

  1. Microsoft.SharePoint.Client (I added version 14.0.4762.1000)
  2. PnP.Framework (I added version 1.11.0)

Next, add a method called GetSharePointContext to get our SharePoint Context object using the PnP AuthenticationManager and another method called GetCertificate that will retrieve your Certificate file.

public static async Task<ClientContext> GetSharePointContext()
{
    var spSiteUrl = ConfigurationManager.AppSettings["SharePointSiteUrl"];
    var appId = ConfigurationManager.AppSettings["AppId"];
    var tenantId = ConfigurationManager.AppSettings["TenantId"];
    var pfxThumbprint = ConfigurationManager.AppSettings["WEBSITE_LOAD_CERTIFICATES"];
    var redirectUrl = ConfigurationManager.AppSettings["RedirectUrl"]
    var certificate = GetCertficate(pfxThumbprint);
    var authManager = new AuthenticationManager(appId, certificate, tenantId, redirectUrl, AzureEnvironment.Production, null);

    return await authManager.GetContextAsync(spSiteUrl);
}

public static X509Certificate2 GetCertficate(string thumbprint)
{
    X509Certificate2 cert = null;
    X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);

    certStore.Open(OpenFlags.ReadOnly);
    X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

    if (certCollection.Count > 0)
    {
        cert = certCollection[0];
        Console.WriteLine(cert.FriendlyName);
    }

    certStore.Close();

    return cert;
}

When I started, I was using authManager.GetContext, and I found the authentication would time out. This is currently an open issue, and can be used by using authManager.GetContextAsync instead.

Since our SharePointContext method is async, we need to call it as follows:

var task = Task.Run(async () => await SPUtils.GetSharePointContext(config));
task.Wait();

context = task.Result;

var web = context.Web;
context.Load(web);
context.ExecuteQuery();

Bonus: APIClientToken.

My Azure Web App has an API that I’m calling from Power Automate. I needed to add another App Setting named APIClientToken. The value has a unique ID that I pass in the header of my Power Automate HTTP request. This is an extra layer of security. Without the token, my HTTP Request would fail.


Date
April 23, 2024
Tags
Architect
Kudos
Buy me a Coffee
Support this site.