SharePoint 2013/2016/2019: Use CSOM in SharePoint Site with multiple authentication schemes

Scenario

I have a SharePoint site collection which has multiple authentication schemes (say Windows NTLM, Azure AD, Okta, ADFS or any other 3rd party Identity provider) on same URL. Now when I try to connect to that site using CSOM, I will get below 403 forbidden error from SharePoint:

The remote server returned an error: (403) Forbidden.

at System.Net.HttpWebRequest.GetResponse()
    at Microsoft.SharePoint.Client.SPWebRequestExecutor.Execute()
    at Microsoft.SharePoint.Client.ClientContext.GetFormDigestInfoPrivate()
    at Microsoft.SharePoint.Client.ClientContext.EnsureFormDigest()
    at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()

Resolution:

A simple resolution is to force the request to use Windows authentication. This works well for scenarios where you want to run a tool for provisioning or do some house keeping stuff for SharePoint.

In order to force CSOM to use windows authentication you need to add below header into all requests.

“X-FORMS_BASED_AUTH_ACCEPTED” : “f”

Here value f, denotes windows auth.

Below is a sample code on how to configure this for a sample csom console application.

Create a new Class called “WindowsClientContext” which inherits CSOM ClientContext class.

Register a web request event handler for the ClientContext, and in this handler add the above request header.

class WindowsClientContext : ClientContext
     {
         public WindowsClientContext(string webUrl) : base(webUrl)
         {
             this.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(AddWindowsAuthRequestHeader); //  register a 
         }
         private void AddWindowsAuthRequestHeader(object sender, WebRequestEventArgs e)
         {
             try
             {
                 if (!e.WebRequestExecutor.RequestHeaders.AllKeys.Contains("X-FORMS_BASED_AUTH_ACCEPTED"))
                     e.WebRequestExecutor.RequestHeaders.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f"); // f to denote that use windows auth
             }
             catch (Exception ex)
             {
                 Console.WriteLine(ex.Message);
                 Console.WriteLine(ex.StackTrace);
             }
         }
     }

Now in your solution use WindowsClientContext instead of ClientContext.

using (var context = new WindowsClientContext(url))
             {
                 try
                 {
                     Web web = context.Web;
                     context.Load(web);
                     context.ExecuteQuery();
                     Console.WriteLine(web.Title);
                 }
                 catch (Exception exception)
                 {
                     Console.WriteLine(exception.Message);
                     Console.WriteLine(exception.StackTrace);
                 }
             }

References:

Retrieving Data from a Multi-Authentication Site Using the Client Object Model and Web Services in SharePoint 2010

Known issue if you are using PnP : PnP clones ClientContext Object for few operations and this cloning process does not clone any web request handler attached to it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s