5

I have an ASP.NET MVC app that connects to SharePoint 2010 via the Client OM. When I run ExecuteQuery(), I get a HTTP 401 error from SharePoint.

I have the MVC app set to impersonate the logged in user.

The impersonate setting in web.config (of the MVC app):

<configuration>
    <system.web>
        <identity impersonate="true" />
    </system.web>
</configuration>

The code:

Client Context ctx = new ClientContext("http://sharepoint.company.com/site");
ctx.Credentials = CredentialCache.DefaultNetworkCredentials;

Web web = ctx.Web;
ListCollection lists = web.Lists;

ctx.Load(web);
ctx.Load(lists);

ctx.ExecuteQuery();

The exception:

System.Net.WebException: The remote server returned an error: (401) Unauthorized. at System.Net.HttpWebRequest.GetResponse() at Microsoft.SharePoint.Client.SPWebRequestExecutor.Execute() at Microsoft.SharePoint.Client.ClientContext.EnsureFormDigest() at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery() at MVCApp.Services.SharePointService.GetLibraries()

When I remove the impersonation setting from web.config, the Client OM uses the MVC app's app pool account to connect. When this happens, the connection is successful (after granting the app pool account permissions). Also, if I hard code a user credential instead of using DefaultNetworkCredentials, the connection works as well.

The app is configured for Windows authentication, and Anonymous authentication is disable in IIS.

Things we have tried:

  1. ensure the app pool accounts are able to delegate permissions.
  2. verified kerberos configuration (we removed some duplicate SPNs)
  3. connect from a different server (we are hosting this app on the SharePoint App Server). Connecting from this server means we can't connect to ANY sharepoint instance. Connecting from another server allows us to connect to our DEV environment, but not this server (QA) or our production environment.

What can I do to get the Client OM to delegate the user permissions when connecting to SharePoint?


Update

Interestingly, I tried a simple WebRequest to SharePoint, with identical results, which tells me that the issue is not caused by the Client OM:

WebRequest request = WebRequest.Create("http://xxxxxxxxx");
request.Credentials = CredentialCache.DefaultNetworkCredentials;

using(WebResponse response = request.GetResponse())
using(StreamReader reader = new StreamReader(response.GetResponseStream()))
{
    return Content(reader.ReadToEnd(), "text/html");
}
2
  • Just for the record, there is a closing '>' in your web.config for the identity item right?
    – Zork
    Jun 8, 2012 at 19:14
  • @Zork I just noticed that and fixed it. Yes, that was a typo. Jun 8, 2012 at 19:20

4 Answers 4

4

This sounds a lot like you are hitting the notorious NTLM Double Hop Problem and I'm sorry to say that there is no way around it aside from changing your authentication to Claims or Kerberos. Neither of which should be taken lightly.

If your code runs on the one of the machines in the SharePoint farm you are attempting to interact with, then you can probably get around this by skipping the second 'hop' altogether and interacting with SharePoint directly via the Object Model on the server rather than through web services.

3
  • We are using Kerberos on the SharePoint side. Do I need to change any settings on the MVC app side? Jun 8, 2012 at 21:11
  • And as for using Server OM vs Client OM: I'm aware of that. The decision was made to use Client OM because this app may end up living on another server without SharePoint installed. Jun 8, 2012 at 21:13
  • If you are using Kerberos then you need to use it all the way from the original user request to your site to the calls to SharePoint
    – Dave Wise
    Jun 8, 2012 at 21:32
2

Almost two years passed but recently I’ve had the same problem with SharePoint 2013 (I’ve actually accessed SP2013 with SP 2010 CSOM libraries). Finally I’ve managed to sort it out.

First, I assume the Kerberos authentication was functioning correctly in you case. Just to be on the safe side, you can turn off NTML authentication in IIS settings or display on your test page

Thread.CurrentPrincipal.Identity.AuthenticationType

Should be Negotiate. There’s no point in trying delegation when you actually log on with NTML, which can happen when you have both allowed.

Next, the update to your question. It helped me a lot, I’ve realized that we shouldn’t worry about CSOM when the simplest delegation with WebRequest doesn’t work. The problem is here.

And finally, this inconspicuous link from the S J answer can actually provide the solution – you mentioned all steps in configuring delegation except allowing delegation for the SERVER. Yes, you must configure that you trust both the account for delegation (which you mentioned) and this specific machine for delegation.

And one more quite obvious thing – the SharePoint itself needs to be properly configured for Kerberos authentication.

Once delegation for a web request works (e.g. loading the start page), you can do the same with CSOM. I’ve tested it, works like a charm.

The difference is that I’ve (1) used SP2013 with 2010 CSOM, (2) turned on delegation just for specific fragment rather than for the whole request:

string ImpersonatedSpLogin = null, ImpersonatedSpMail = null;

WindowsIdentity identity = (WindowsIdentity)User.Identity;
using (var impersonationContext = identity.Impersonate())
{
    using (ClientContext context = new ClientContext("http://myServer.somewhere.com/"))
    {
        context.Load(context.Web.CurrentUser);
        context.ExecuteQuery();
        ImpersonatedSpLogin = context.Web.CurrentUser.LoginName;
        ImpersonatedSpMail = context.Web.CurrentUser.Email;
    }

    impersonationContext.Undo();
}
// now you can verify by checking  ImpersonatedSpLogin and ImpersonatedSpMail

Hope that helps anyone.

0

Do you have <authentication mode="Windows" /> in there somewhere as well? I believe that is also required.

The below link has some information on the output of a few variables based on the configuration settings of the web.config and IIS

https://stackoverflow.com/a/1688220/1282079

4
  • Yes, the app is configured for Windows Authentication, and Anonymous access is disabled. Jun 8, 2012 at 19:50
  • When I write the values of the variables in the answer you linked to, I get results as described in the last example, yet the connection to SharePoint still gives a 401. Jun 8, 2012 at 20:04
  • Dang, the only difference i see anywhere i look is that most people use the using statement to ensure everything is properly disposed (best practice), but I cant find anything else, sorry.
    – Zork
    Jun 8, 2012 at 20:22
  • And I am doing that, I just distilled the example for this question. Thanks for taking a look. :) Jun 8, 2012 at 21:12
0

Does the below link help? I am also facing a similar problem.

https://stackoverflow.com/questions/11691650/getlistitems-request-failed-with-http-status-401-unauthorized/11843756#11843756

1
  • 1
    Some information as to why the url would be of help, would be more useful to people when scanning answers.
    – Hugh Wood
    Nov 22, 2012 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.