Azure Web App authenticating to SharePoint with an App Registration and Certificate
June 27, 2024ā¢794 words
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.
- Create a Self-Signed Certificate.
- Create an App Registration.
- Prepare the Azure Web App.
- 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 how to Create an Azure App Registration with SharePoint access.
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.
- Open your Web App, then, click
Certificates
on the left navigation. - Select
Bring your own certificates (.pfx)
tab. - Upload the
.pfx
file that was created inStep 1
. - Enter your .pfx password during the upload.
- 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.
- Open your Web App, then, click
Environment Variables
in the left navigation. - Add a new
App Settings
variable. - Name the variable
WEBSITE_LOAD_CERTIFICATES
. This needs to be exact. - Set the value of the variable to your
Thumbprint
you copied in step 3a. - 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. TheGetCertificates
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.
- WEBSITELOADCERTIFICATES: 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:
- Microsoft.SharePoint.Client (I added version 14.0.4762.1000)
- 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 usingauthManager.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.