Allowing Anonymous Access with SharePoint Web Services and SPServices
Over the last few days or so, Christina Wheeler (@cwheeler76) and I were trying to figure out why my jQuery Library for SharePoint Web Services (SPServices) wouldn’t work when SharePoint was enabled for anonymous access. I had always assumed that it was just one of those things. Even though I couldn’t find any definitive documentation on it, there was enough speculation and innuendo that anonymous access and the Web Services wouldn’t mix that I just wrote it off.
Well, Christina posted a fantastic article on EndUserSharePoint.com last week called Real World Project: Transparent Overlays for SharePoint Interface Enhancement. In it, she described how she used some slick CSS tricks with the SharePoint Web Services and SPServices on a client’s home page for their Internet-facing site. Christina and I had even looked at an early version of the page together while she was working on it and I gave her some tips on how best to use SPServices. Somehow, though, we never talked about the fact that she needed anonymous access to work. We both missed that little wrinkle.
Skip forward a few days and she got a call from the client, wondering why people were being prompted for credentials. Uh-oh. I had steered her wrong on the use of SPServices. That was enough impetus right there to get to the bottom of the anonymous access with Web Services issue.
Well I’m happy to say that after some fiddling and help from Christina that I believe we’ve got it figured out. I had been *always* passing the SOAPAction in the RequestHeader. Everything that I had read had told me that was required, even the Web Services documentation in the SDK on MSDN. Christina pointed out this article from Jan Tielens: The security validation for this page is invalid" when calling the SharePoint Web Services. It also describes the problem and the solution using SOAPAction.
It turns out that you don’t need to pass the SOAPHeader if the Web Service operation is a read-only one. For instance, some of the most useful things, like GetListItems, don’t require it. In my testing, *none* of the read-only operations need the SOAPHeader. Oddly, if you don’t pass it with the read/write functions, they only fail if you *are* authenticated, the error says that you *aren’t* authenticated, and that you should hit the back button and refresh. Well that’s hardly helpful given that you aren’t working interactively, but talking to the Web Services programmatically.
So the solution was pretty simple, once I know what was going on. I added a new element to the WSOps array [true | false] for the requirement of SOAPAction. (The WSOps array is where I store which Web Service each operation belongs to.) All of the read-only operations are set to false, and the rest are set to true. If the value is false, I don’t pass the SOAPAction: problem solved. I released v0.5.3ALPHA2 with this fix tonight, and I’m pretty sure this method is a keeper.
This will be a great improvement to the library, allowing its use on public-facing Web sites. This is pretty exciting, really, as those are the sites where you are most likely to want to have real a Web 2.0 (whatever that means) feel to the site pages.
Hi Marc
Not sure if you will monitor this but I am trying to use SPServices to read data from a list on a public internet site that is running SharePoint 2007. I assumed that it would work for anonymous access but once we publish the page no data is returned. No error is returned either but when I test Status it does not = ‘success’. Is there a way to get the error message on the completefunc Status?
Everything works great when logged into the authoring site (using https) but it does not work with http. Any help would be greatly appreciated.
pm:
If the list is set to allow anonymous access, you should be able to read from it using GetListItems. Take a look in Firebug’s Net tab or Fiddler to see what the full returned XML looks like. Odds are it will tell you something about what’s going on.
M.
Hi Marc
Thanks for responding so soon. It looks like the issue is anonymous users being able to access the /_vti_bin/Lists.asmx file. When my code tries to read from a list Firebug shows a POST to Lists.asmx but it shows the location as a PageNotFound page in the Response Header.
The lists all allow Read access to anonymous users so that should not be an issue. Any other thoughts? Do you need any further info?
Thanks, PM
Hi Marc
I have found out it is an internal proxy server problem. Sorry, and thanks for your help.
PM
Hi Marc
My last comment was premature. What the IS guys here found out was that in IIS there was a mod rewrite for URLs in the _vti_bin directories to be redirected to the page not found. They added an exclusion to the rule to allow access to webs.asmx and list.asmx and now everything works. However, we think this may be a security issue and were hoping you could give us your opinion.
Thanks, PM
pm:
Blocking the asmx Web Services is likely to cause more harm than good. I’m surprised you haven’t seen other issues. The Web Services respect all permissions, so users can’t do anything with them that they can’t do through the UI.
M.
Thanks Marc.
Hi Marc
Just to clarify things, we only had anonymous access to list.asmx and webs.asmx blocked. And unblocking this allows us to use SPServices to read from a list. Our concern is that unblocking anonymous access could allow a security issue. I have been searching this topic but can’t find a clear consensus as to whether this is a security issue or not.
pm:
I’ve already answered your question: “The Web Services respect all permissions, so users can’t do anything with them that they can’t do through the UI.”
M.
Thanks Marc, this has saved our day for a SharePoint 2013 public site. We didn’t want the security risks associated with disabling “Require Use Remote Interfaces permission” that is required when using CSOM\REST anonymously. Much appreciated.
Marc:
Glad to hear it was useful!
M.
Hi Marc
Thank you for your extraordinary work.
Having trouble adding a list item to a WSS 3.0 anonymous enabled site. We were getting the credentials prompt, but after our Admin did some IIS / WSS config fiddling… there is no prompt and write attempts now just silently fail with a 401 unauthorized status for lists.aspx in the console.
Thoughts? Are there any often overlooked places where anonymous needs to be enabled?
Paul:
Anonymous writes are a problem in general with SharePoint. SharePoint wants to record someone in the Created By (Author) and Modified By (Editor) fields and cannot when anonymous access is enabled. Assuming you have anonymous access enabled on the list, you may not be able to make these write calls. Even if you can, the contents of the list will be non-secure. I would also recommend against trying to fiddle with IIS to resolve this as it may have other, unintended consequences.
M.
Sadly, I’m still running into this issue. I’m working in SharePoint 2010, using the latest SPServices and jQuery builds (although I’ve tried multiple variations of each), and using GetListItems to pull from an announcements list on a public facing site. The site and list are both enabled for anonymous access. The list data displays fine on the page while logged in on the admin side, but when I view the page anonymously, no data is displayed. Any suggestions on other things to check? Thank you!
Just to confirm, its supposed to just work for an anonymous user to fill out a form and have SPServices work anonymously to create a new item in a list? I am stuck still getting auth prompts in my solution. I have SP 2013 and am just trying to get a basic contact us form to work. Here is the page: http://www.altoconsulting.com/pages/formtest.aspx and here is my code:
Choose a subject…
Sales Information
Employment Opportunities
Training Information
Available Courseware
Website Feedback
General Inquiries
Office 365 Support
Contact Us
$(document).ready(function () {
$(“#ContactUsBtn1”).click(function () {
var name = $(“#Name”).val();
var email = $(“#Email”).val();
var phone = $(“#Phone”).val();
var subject = $(“#Subject”).val();
var message = $(“#Message”).val();
AddListItem(name, email, phone, subject, message);
alert(“before AddListItem Function”);
});
});
function AddListItem(name, email, phone, subject, message) {
$().SPServices({
operation: “UpdateListItems”,
async: false,
batchCmd: “New”,
listName: “ContactUsList”,
valuepairs: [[“Title”, name], [“Email”, email], [“PhoneNumber”, phone], [“Subject”, subject], [“Message”, message]],
completefunc: function (xData, Status) {
//alert(xData.responseText);
alert(“Thank you, we will be in touch shortly.”);
window.location.href = window.location.href;
}
});
}
I have all the anonymous turned on and I know it works because I also have an InfoPath form for that list that does work anonymously. Anyone have any ideas? It looks like its failing on lists.asmx, but an anonymous user can also access that full url just fine.