ColdFusion/Sharepoint Integration - Part 1 - Authenticating
Posted By : todd sharp Posted At : March 17, 2008 11:04 AM Posted In: Sharepoint, ColdFusion
30
I've been working a bit with Sharepoint lately for some team sites at work and needed a way to dynamically manage some user lists for a given site. Since Sharepoint has a pretty extensive API for interacting with the various bits I figured it would be pretty simple to create a scheduled task in ColdFusion that would pull a list of valid userid from my database and pass the list to Sharepoint to keep the authentication up to date without much intervention on my behalf.
Turns out it wasn't quite all that simple to even connect to the Sharepoint service. My attempts at setting/passing my NT credentials on the webservice call kept resulting in a 401 (Unauthorized) response from the service. Eventually I came across this post from Tom Jordahl that presented a fix. Let me quote Tom's post since he does a good job explaining:
Someone asked me how they could turn on NT Authentication for web service using Apache Axis (the web service used by ColdFusion). By default Axis uses its own HTTP client code, org.apache.axis.transport.http.HTTPSender, to send the XML/SOAP POST requests to a web service. This uses HTTP 1.0 and generally works file.Axis also supports the Jakarta Commons HTTPClient library, and has since 1.0. To configure Axis to use this instead of its own library you must edit the client-config.wsdd file used by Axis. It gets found on the classpath and generally you don't actually have one and the one built in to axis.jar gets used. The interesting line is the http transport. To switch Axis to use the HTTPClient jar, you would change this:
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"></transport>To this:<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"></transport>Once you have this code configured, Axis will use the HTTPClient library for it HTTP needs. Since the HTTPClient library supports NT Authentication, you just set the username/password on the Stub object as you would normally do for (say) Basic Authentication and it will just work. If you are talking to a .NET web service, you are done.
So as he says, I made the change and "it just worked". I can now interact with the Sharepoint user service. Honestly, I haven't done a thing other then confirm that I can now authenticate at this point. Which is why I named this 'Part 1' - because I have a sinking suspicion that my journey to CF/Sharepoint enlightenment will have a few other bumps along the way.
As a side note, I am a bit unhappy that I had to mod the client-config.wsdd file to get this to work. If anyone knows of a simpler workaround please let me know.

<Cfset ws=createobject("webservice","http://websitename/sites/sitename/_vti_bin/lists.a...;)>
<Cfdump var="#ws#">
Did you try the url directly in your browser to make sure you can view the WSDL?
Did you restart CF after making the change to the config file?
From my desktop I do not have to authenticate in the browser. When I do it from the server (local admin logged in, CF running under with another domain users credentials), I do have to autheticate with my domain credentials.
I don't know how to make this authentication happen in my code. The examples I have seen set the username password AFTER creating the webservice. I can't get that far.
Check your email.
Todd
I don't know if you're still following this post or not, but I bet your problem is one that I was having earlier. If the WSDL is actually using NTLM then you can't authenticate against it and you can't get the stubs to generate. To solve the problem access the WSDL from your browser and save it into a folder on your webserver. Then point your CFObject call to the file you've saved on your server. This will let the stubs generate but since the WSDL came off the sharepoint server originally all the method calls will still go to sharepoint. (I can't remember whose blog I found this tidbit on but it sure does work).
Can you email me an example of your call to the service and the error that is being thrown?
Todd
http://livedocs.adobe.com/coldfusion/7/htmldocs/ww...
You mention getting success with the approach Tom offered, but it seems you had to (as he said) pass the username/password. What if we don't want to prompt the user for that (or retrieve it from somewhere we stored it for them)? Is there any way to pass it along on their behalf?
I've also asked on Tom's blog entry you point to, but I don't know if he'll respond.
Also, did you ever do a part 2? I couldn't find it.
Also, the next FAQU has my article on CF/SharePoint with some pretty detailed examples (which is essentially part 2 of my blog post). It got bumped from the last issue for some reason, but I'm 95% sure it'll be in the next one that's coming out soon.
Could you or jenn post (or email) some more tips on how you guys got this working? It would be a life saver!
I'd be glad to give you some more help...
I was going to try and email you, but you're address isn't in the post that I see. If you want to send me a line at jdodson@pioneerservices.com feel free. If you include in the email what errors (if any) you're getting that would also be helpful. This project was one of the most frustrating I've ever done so I'd like to save someone else some of the steps.
There is so little info on the internet about this, I will try and ask you my question right here.
I have a little colfusion page that I view through a Page Viewer Webpart in Sharepoint. The only thing I want from sharepoint is the logged in user. I found bits of code to get that, but it's always from .NET, I don't know how to do the same thing with Coldfusion. Any ideas?
Thanks,
http://labs.adobe.com/technologies/coldfusion9/
Good luck!
I've started working on a project that will interact with Sharepoint, but unfortunately my company is stuck with ColdFusion 7. So, no cfsharepoint tag for me... When did the FAQU article come out?
Thanks,
Many thanks
We did figure it out. We used what I feel is kind of a crazy mix of java and coldfusion and it worked out fine. Basically we've got a CFC with a whole bunch of inline java (what a nifty thing to be able to do). It's been working like a champ for almost two years now. If you have a specfic thing you're trying to do let me know and I'd be glad to help you out... though I haven't been in that code for awhile so I'm kind of rusty on it.
Thank you for taking the time to reply. We are trying to use UpdateListItems to do two things: add an item to a list and upload a document to a document library. However, we haven’t been able to figure out how to format the second parameter of the method. As you mentioned earlier, according to the documentation, it looks pretty simple: a piece of XML.
<Batch>
<Method ID='1' Cmd='New'>
<Field Name='Title'>First item of list</Field>
</Method>
</Batch>
However, no matter how we set the xml argument, we get the error message “Web service operation UpdateListItems with parameters {parameters_here} cannot be found.” We tried adding some inline java but got a type mismatch error.
I would truly appreciate it if you could shed some light into how we need to pass this parameter...
Once again, thanks.
I've been trying to consume UpdateListItems since your last email and I'm still getting nowhere. You mentioned you used some inline Java. Can you provide more details?
Thank you,
<cffunction name="updateListItems" output="true" returnType="String" hint="Updates the items in a list or adds new items based upon the contents of the updates array">
<cfargument name="listGuid" type="String" required="Yes" hint="The GUID of the list being updated">
<cfargument name="listVersion" type="String" default="1" hint="the List version, in case there is more than one">
<cfargument name="viewName" type="String" default="" hint="The view to use when updating... normally left blank">
<cfargument name="updates" type="any" required="Yes" hint="The actual update information in the form of a struct">
<cfscript>
var doc = "";
var batchXML = "";
var updateElement = "";
var curMethod = "";
var finalParam = arrayNew(1);
var xmlResponse = "";
var xPath="/ns1:Results/ns1:Result/ns1:ErrorText"; //Look for the error text nodes
var errorList = "";
</cfscript>
<CFOBJECT type="java" class="com.microsoft.schemas.sharepoint.soap.UpdateListItemsUpdates" name="Element" />
<CFOBJECT type="java" class="javax.xml.parsers.DocumentBuilderFactory" name="DocumentBuilderFactory"/>
<CFOBJECT type="java" class="org.apache.axis.message.MessageElement" name="MessageElement">
<cfscript>
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
batchXML = doc.createElement("Batch");
batchXML.setAttribute("OnError", "Return");
batchXML.setAttribute("ListVersion", "1");
batchXML.setAttribute("ViewName", "");
</cfscript>
<cfloop from="1" to="#ArrayLen(updates)#" index="i">
<cfset curMethod = buildMethodElement(doc,updates[i][1],"#i#",updates[i][2])>
<cfset batchXML.appendChild(curMethod)>
</cfloop>
<cfscript>
finalParam[1] = MessageElement.init(batchXML);
updateElement = Element.init(finalParam);
</cfscript>
<cfinvoke webservice="#sList#" method="UpdateListItems" returnVariable="Results">
<cfinvokeargument name="listName" value="#arguments.listGUID#"/>
<cfinvokeargument name="updates" value="#updateElement#">
</cfinvoke>
<cfset xmlResponse = Results.get_any()>
<cfset xmlResponse = xmlParse(xmlResponse[1])>
<cfset FieldArray = XmlSearch(xmlResponse,xPath)>
<cfloop from="1" to="#ArrayLen(FieldArray)#" index="i">
<cfset errorList = FieldArray[i].XmlText>
</cfloop>
<cfreturn errorList>
</cffunction>
You will need to get the appropriate java classes on your class path. We did that by sticking them in a folder called stubs and putting the whole thing on the path. You can get the clases from the Sharepoint server I believe.
Good luck
Turns out the solution to all my problems was to enable basic authentication via the SharePoint's Central Administration under Application Management > Authentication Providers. Once you go into the detail for your zone (this will probably be the "default" zone) you just go down and check Basic authentication. In my case I had only NTLM Integrated authentication checked.
Hope this helps someone else having authentication problems with cfsharepoint. You CAN use it with NTLM as long as you ALSO have basic authentication checked.
P.S. I tried the trick above changing the client-config.wsdd file used by Axis and it made no difference. The key was enabling basic auth via sharepoint central admin.