Link to home
Start Free TrialLog in
Avatar of mike_wb
mike_wb

asked on

The remote server returned an error: (401) Unauthorized - How can I fix, or do a workaround?

I am developing company web site with ASP.NET, where I am using C# to post a question i.e. social content, to a company SharePoint community. The SharePoint site uses NewsGator for social content. This is all happening on a company intranet. The website was developed using VS2008, and the .Net Framework 3.5. The SharePoint site is on a company farm.

When I use the web app from my workstation via the IDE, it works great!, and the question gets successfully posted to the SharePoint Community- Woohoo! But after I publish the web app, to our development environment on a single Windows 2008 R2 server (which resides on a different domain BTW), I’ll use the web app from the server, and when I try to post a question, and I get a error: “The remote server returned an error: (401) Unauthorized.” My code is included as well as the error info.

How can I work around this issue. Keep in mind, I want to do this work around in my code, Doing the workaround on the SharePoint server farm (which is in production) is not an option. Virtually the same applies for the web server, because the app will eventually be on a production web farm.  
    public class ReSTService
    {
       public string HttpPost(string url, string[] paramName, string[] paramVal)
        {
            HttpWebRequest rqst = WebRequest.Create(new Uri(url))as HttpWebRequest;
            rqst.UseDefaultCredentials = true;
            rqst.Method = "POST";
            rqst.ContentType = "application/x-www-form-urlencoded";

            StringBuilder sbParams= new StringBuilder();
            for (int i = 0; i < paramName.Length; i++)
            {
                sbParams.Append(paramName[i]);
                sbParams.Append(HttpUtility.UrlEncode(paramVal[i]));
            }

            byte[] formData = UTF8Encoding.UTF8.GetBytes(sbParams.ToString());
            rqst.ContentLength = formData.Length;

            using (Stream post = rqst.GetRequestStream())
            {
                post.Write(formData, 0, formData.Length);
            }

            string result = null;
            using (HttpWebResponse resp = rqst.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(resp.GetResponseStream());
                result = reader.ReadToEnd();
            }
            return "";
        }
    }

Open in new window


Error Info:
Process information:
    Process ID: 3760
    Process name: w3wp.exe
    Account name: IIS APPPOOL\sswtool
 
Exception information:
    Exception type: WebException
    Exception message: The remote server returned an error: (401) Unauthorized.
 
Request information:
    Request URL: httppathhidden/for/thispost/default.aspx
    Request path: /rootDirNameHidden/ssw/default.aspx
    User host address: xx.xx.xx.125
    User: xxx\myID
    Is authenticated: True
    Authentication Type: NTLM
    Thread account name: IIS APPPOOL\rootDirName
 
Thread information:
    Thread ID: 3
    Thread account name: IIS APPPOOL\rootDirName    Is impersonating: False
    Stack trace:    at System.Net.HttpWebRequest.GetResponse()
   at theNameSpace.ssw.ReSTService.HttpPost(String url, String[] paramName, String[] paramVal) in pathhidden\for\thispost\classes\ReSTService.cs:line 40
   at theNameSpace.ssw.Default.askButton_Click(Object sender, EventArgs e) in pathhidden\for\thispost\classes\Default.aspx.cs:line 47
   at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
 
 
Avatar of Moomin83
Moomin83
Flag of South Africa image

Hi Mike

I assume you are using IIS 7.5 (Server 2008 R2) 401 indicates authentication problems with either Basic, Digest or Windows Authentication.
 User generated imagePlease ensure you have the correct Authentication type selected/enabled (example uses windows integrated authentication)
 User generated imageAlso ensure that your app pool has the correct settings (found under advanced settings)
 User generated image
My answer is based on a assumption, please advise if I understood it correctly.
Sorry, i missed the part of changing it in code.
Avatar of mike_wb
mike_wb

ASKER

No problem Moomin83, thank you, I will take your comment into consideration anyway. If it ends up helping reslove the problem, I will follow up with the info and points
Mike
Do you plan on setting up your web application (the app where your code is running) under a specific user context when it is running?  Because whatever user context your app is running under is going to have to be granted permission to post to the SharePoint site.  It probably works on your dev machine because when you run in debug mode the web app is generally going to run under your user credentials.

The setup of the user isn't going to be something your application can do unless you build something that allows an admin that has the rights to setup the user to plug in their credentials so that the app can impersonate them in order to setup the accounts.
Avatar of mike_wb

ASKER

Hi Volox:
Not sure what you mean by specific user context, would that be like a process ID and pw?  I'll have to google that.

Do you think the problem might be as simple as this:
It will work from my workstation because it resides on the same domain, as the domain of the sharepoint site that I have authorized access to, but the the app deployed to the webserver of a different domain, cannot access the the sharepoint site because it is passing the wrong domain in my credentials?

Or do you think it is more complicated than that?

 
It's slightly more complicated than that.  A web application runs under a user context (just like any process has to).  If you don't configure the user under which your web app runs, then it is running as the IIS worker process; that account isn't going to have rights anywhere outside of the machine on which it is running.

Now as you can see in the screenshots by Moomin83, there is a setting for "Identity" within the IIS setttings.  This can be used to control what user account the website's application pool runs under.  (more explanation here http://learn.iis.net/page.aspx/624/application-pool-identities/ )

All that being said, if you were to secure your web application so that it is running under Windows Authentication, then your code can impersonate the user that is logged into the site and use those credentials.  However I'm not a super huge fan of this myself do to potential security issues this can create (I'll let you research that religious debate on your own).

What I would recommend would be to create a user account that you run your website under by configuring the application pool to use that account.  However, if the machine where the web app is deployed isn't in the same domain as the machine that SharePoint is on, then this doesn't work cleanly because you can't provide the same user on both machines.  So knowing your deployment scenario is important in this case.  Can you provide info on the deployment situation?
Oh, and if your machines aren't in the same domain you will probably need to do something similar to this....

rqst.UseDefaultCredentials = false;
rqst.Credentials = new NetworkCredential(username, password);

Not sure if that's precisely what works with SharePoint because I don't have a SP server to test against right now, but it should head you in the right direction if you can't use the web application identity to solve your issue.

Of course, then you have the issue of how to store the username and password safely so that they won't be compromised if your web app gets compromised.  (which is why I much prefer the method of setting the user identity of the web app to something that will automatically provide access if that is at all feasible)
Avatar of mike_wb

ASKER

While I am still gratefully reflecting on and analyzing this information, I can share this much now

This is a unique/unusual deployment situation, here are some facts:
1) My workstation where I do my web development is on the prod domain (not unusual)
2) The server where I deploy the app to test, is on a test domain (not unusual)
3) The SharePoint sandbox I was provided, resides on the prod domain. (very unusual) - its being called a sandbox, because only a few of us on the project team, have access to the communtiy. It would enventually be available to all authenticated users on the company intranet when its not a sandbox anymore.

Clues:

rqst.UseDefaultCredentials = false;
rqst.Credentials = new NetworkCredential(username, password,domain);

I added the above code, deployed to and ran from the test server, and it worked with sharepoint like I wanted. Of course we don't want to it this way, but I hope it provides a clue.

GTG: more info to come
Thank You
ASKER CERTIFIED SOLUTION
Avatar of Volox
Volox
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mike_wb

ASKER

All of your info was helpfull, For now at least have now have a work around for demonstration purposes. Thank You