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)
 
 
mike_wbAsked:
Who is Participating?
 
VoloxCommented:
That definitely helps.

Does your test domain trust your prod domain?  In other words, can you use credentials from the prod domain to assign rights to things in the test domain?  If so, then you can still run your app in the test domain under a prod account.  If not, then you're kind of stuck with a test environment that is going to have to work differently than your prod domain.

If that's the case, what you might do is this... you might build your app so that it looks for a setting in the config to tell it to pull the username and password information out of the config.  If the setting isn't present or is set to not pull from config, then you use the default credentials.  This would allow you to use a specific set of crendtials when you run the application in test and use the method of setting up the website under a specific account when you are in prod.
0
 
Moomin83Commented:
Hi Mike

I assume you are using IIS 7.5 (Server 2008 R2) 401 indicates authentication problems with either Basic, Digest or Windows Authentication.
 IIS 7.5Please ensure you have the correct Authentication type selected/enabled (example uses windows integrated authentication)
 authenticationAlso ensure that your app pool has the correct settings (found under advanced settings)
 app pool
My answer is based on a assumption, please advise if I understood it correctly.
0
 
Moomin83Commented:
Sorry, i missed the part of changing it in code.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
mike_wbAuthor Commented:
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
0
 
VoloxCommented:
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.
0
 
mike_wbAuthor Commented:
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?

 
0
 
VoloxCommented:
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?
0
 
VoloxCommented:
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)
0
 
mike_wbAuthor Commented:
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
0
 
mike_wbAuthor Commented:
All of your info was helpfull, For now at least have now have a work around for demonstration purposes. Thank You
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.