Download document from SharePoint (NTLM Authentication)

I am trying to download a document from an (Old) SharePoint library in a Jython script. When I attempt to open the document with either "requests.Get" or "system.net.httpGet" I get 401 (Unauthorized).
I believe the reason for this is that I need to use NTLM authentication because the HTTP response contains:
'WWW-Authenticate': 'NTLM'

As far as I can tell there is no way to specify NTLM authentication header in the version of these libraries found in Ignition, does anyone have any ideas?

You're correct, there's no built-in ways to do this in Ignition. You have a couple options; you could attempt to assemble the right authentication header yourself, but as far as I understand NTLM it requires a few roundtrips, so it's a bit involved.
You might be able to extend requests, if you've already got it installed, with the requests-ntlm module:

I have no idea if it will work in Jython's environment or not.
You could also create a module (or drop in one or more .jar files in the appropriate location) that exposes Java library code to create an NTLM client connection.

I've been using this successfully for a couple of months to get our ArcGIS data into perspective with no issues

1 Like

@PGriffith
PIP install requests-ntlm fails to install so that looks like a dead end

@Matthew.gaitan
I copied the code on the thread you shared and I got a success code straight away!.. But I don't know how to actually download the file as the line content = BasicResponseHandler().handleResponse(response) returns a string, but the file I am downloading is an .xls so I need to access it as binary file, not plain text.
I tried using response.getEntity().getContent() but this returns an 'org.apache.http.conn.EofSensorInputStream' but I don't know how to convert that to a byte stream Python can read.

@Matthew.gaitan Any ideas on how to get a binary stream instead of a plain text stream?

Not sure, sorry. I've (thankfully) never had to deal with sharepoint integrations via ignition.

After a quick google search:

I would try the first response using EntityUtils.toByteArray

with an import statement of from org.apache.http.util import EntityUtils

No clue if this will actually work though

1 Like

Here is what I use, can work for files just need to modify the return...

def httpGetNTLM(url):
	from org.apache.http.auth import AuthScope
	from org.apache.http.auth import NTCredentials
	from org.apache.http.client.methods import HttpGet
	from org.apache.http.impl.client import DefaultHttpClient
	from org.apache.http.impl.client import BasicResponseHandler
	from org.apache.http.entity import ContentType
	from java.io import ByteArrayOutputStream
	
	# Setup the client with NTLM Auth
	httpclient = DefaultHttpClient()
	
	# Define the credentials to use
	creds = NTCredentials(username, password, system.net.getHostName(), "DOMAIN")
	httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds)
	
	# Define the host and URL to call
	httpget = HttpGet(url)
	
	# Execute the request
	response = httpclient.execute(httpget)
	
	# Get response entity and MIME type
	entity = response.getEntity()
	contentType = ContentType.getOrDefault(response.getEntity()).getMimeType().lower()
	
	# Return the result
	if 'json' in contentType:
		return system.util.jsonDecode(BasicResponseHandler().handleResponse(response))
	elif contentType in ["image/png", "image/jpeg"]:
		baos = ByteArrayOutputStream()
		entity.writeTo(baos)
		return baos.toByteArray(), contentType
	else:
		return BasicResponseHandler().handleResponse(response), contentType
2 Likes

Thanks @Matthew.gaitan that was the last part I needed

My final code:

# Perform a basic HTTP Get to the provided URL using the NTLM auth in the function
def DownloadFile(remoteFile, localFile):	
	from org.apache.http.auth import AuthScope
	from org.apache.http.auth import NTCredentials
	from org.apache.http.client.methods import HttpGet
	from org.apache.http.impl.client import DefaultHttpClient
	from org.apache.http.impl.client import BasicResponseHandler
	from org.apache.http.entity import ContentType
	from org.apache.http.util import EntityUtils
	
	# Setup the client with NTLM Auth
	httpclient = DefaultHttpClient()
	
	# Define the credentials to use
	creds = NTCredentials(username, password, system.net.getHostName(), domain)
	httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds)
	
	# Define the host and URL to call
	httpget = HttpGet(remoteFile)
	
	# Execute the request
	response = httpclient.execute(httpget)
	
	# Copy the file
	with open(localFile, "wb") as output_file:
		output_file.write(EntityUtils.toByteArray(response.getEntity()))