Setting up Web Login with PnP Framework

If you've worked with SharePoint Online and C#, you're likely familiar with the SharePointPnPCoreOnline SDK. It allows you to easily connect to SharePoint and handle user authentication.

Unfortunately, PnPCore is now deprecated and replaced with the newer PnP Framework. Framework is almost exactly the same, but there's one glaring ommission, the ability to have users login using the Web Login Form. If you use MFA (you are using MFA, right?) this used to be the easiest way to get your users logged in.

Microsoft's official FAQ on the on the subject explains the ommission as being a trade-off that the Web Login was only supported on Windows, so couldn't be included for compatibility reasons. They then suggest that you copy the implementation from PnP Powershell. OK...but how does that work?

It's actually not that difficult, but there are some things to be aware of. I also ran into a bug, which I'll outline below along with my fix.

Start by adding PnP.Framework to your project from NuGet. In my own project, I'm running .Net 6, but this should also work for .Net 5.

Create a new class file named BrowserHelper.cs. I've attached a copy of the content at the bottom of this post, but you can find Microsoft's original file here: BrowserHelper.cs

If you use Microsoft's copy of the file, you'll need to make the following adjustments:

1 - Add the CookieReader class (either as a separate file, or just appended to the BrowserHelper.cs file) Here's a link to Microsoft's original file: CookieReader.cs

2 - This is the bug fix. When I first tested logging in, my app just froze as soon as the Web Login window closed. I eventually traced the issue to an asynchronous http request that never completed. Checking with Fiddler, the actual request was made and completed very quickly, but the await was never notified for some reason. The fix is very simple...just switch to a synchronous call. You need to update the function GetRequestDigestAsync. Change the line "HttpResponseMessage response = await httpClient.SendAsync(request);" to "HttpResponseMessage response = httpClient.Send(request);"

If you use the copy of the BrowserHelper.cs file attached below, both of these updates have already been made.

Finally you need to update your project to add a Conditional Compliation Symbol. You'll find this in your Project Properties under Build...General. Just add "Windows" to the end of the existing symbols. Mine looks like this: "$(DefineConstants)TRACE;Windows". Please be aware that setting this value limits you to Windows. If you're creating something for Linux or Mac, you'll have to use the alternative methods for authenticating.

Now that you have your BrowserHelper file ready, you can authenticate in your app. You should probably Clean and Rebuild your project first.

Here's the line to authenticate and create your context: "var context = BrowserHelper.GetWebLoginClientContext(url, true);"

The url is the address of your SharePoint site. The boolean value is whether or not you want to clear your cookies first. I recommend setting that to true.

Now that your context has been created, you're up and running! I hope this has been helpful.

BrowserHelper.cs with fixes: