401 Unauthorized Access Error with SharePoint NTLM Authentication

Hafiz Hussain
2 min readJan 18, 2020

I am writing this post after I fixed an issue with SharePoint file upload APIs at one of our clients’ environment.

Note: The url, token and other API data I used in this article is either JUNK or generic parameters.

The problem was whenever I tried calling the file upload service http://hostname/repo_name/_api/web/getfolderbyserverrelativeurl('foldername')/files/add(overwrite=true, url=’test_file.docx’)

I got 401 Unauthorized Error.

The issue was, X-RequestDigest was going as null in the headers.

How do we get this RequestDigest?

Please go through this article, if you want to know what RequestDigest is

https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/basics/working-with-requestdigest

By calling the API http://{{sharepoint_hostname}}/{{project_name}}/_api/contextinfo

I achieved this with a simple .NET C# console application.

Simple .Net Console Application:

I am assuming the readers know how to create a simple .Net console application in MS Visual Studio. If not please visit the following link to create one.

In the Main function of the console app, I created a HTTP client get request with the following headers and parameters.

var uri = new Uri("http://{{sharepoint_hostname}}/{{project_name}}/_api/contextinfo");
var credentialsCache = new CredentialCache { { uri, "NTLM", new NetworkCredential("testusername", "testpassword", "") } };
var handler = new HttpClientHandler { Credentials = credentialsCache };
var httpClient = new HttpClient(handler) { BaseAddress = uri };
httpClient.DefaultRequestHeaders.ConnectionClose = false;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("DataServiceVersion", "3.0");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Host", "riskprocessuat.indusind.com");
ServicePointManager.FindServicePoint(uri).ConnectionLeaseTimeout = 120 * 1000; // Close connection after two minutes
var response = httpClient.PostAsync(uri, null).Result;
string respdata = await response.Content.ReadAsStringAsync();
Console.WriteLine(respdata);

For the given code, when the API is called, we get the request digest along with different parameters which looks some like this.

0xDAABCE0ABCDEF12345F589B1A1EABD258999CA8B225F96C944204AFA83813CF728FE7234F588E027FCB5BF9E21C3D06DBE1CFE7D19507AE687681E6A,19 Jan 2020 15:09:54 -0000 (Example JUNK Token)

With the above key as RequestDigest, I called the API to upload file to SharePoint with the following headers

"headers": {
"X-RequestDigest": "0xDAABCE0ABCDEF12345F589B1A1EABD258999CA8B225F96C944204AFA83813CF728FE7234F588E027FCB5BF9E21C3D06DBE1CFE7D19507AE687681E6A,19 Jan 2020 15:09:54 -0000",
"username": "testusername",
"password": "testpassword",
"Accept": "application/json;odata=verbose",
"Content-Length": "2",
"Content-Type": "text/plain"
}

When the service is called, I got response status as 200 instead of 401 Unauthorized and we were able to see the file at SharePoint site which we wanted to upload.

Please leave a comment, if there are any queries with this Authentication.

--

--