Trouble downloading a file - c#

I am trying to download a file from a C# application. I have tried two different methods, but both yield the same response:
"The remote server returned an error: (401) Unauthorized."
I am pretty sure this is a credentials issue (because of the 401). If I navigate to the url from a browser, and enter the very same credentials provided, the file downloads just fine. In "Attempt 2" (below), for authtype, I have tried:
NTLM, Basic, Negotiate, and Digest without any luck.
Does anyone see what I might be doing wrong here?
Thanks for the help!
Attempt 1:
string username = "username";
string password = "password";
string domain = "domain";
string url = #"http://LiveLinkInstance.com/livelink/llisapi.dll/999999/WordDocument.docx?func=doc.Fetch&nodeid=999999&ReadOnly=True&VerNum=-2&nexturl=/livelink/llisapi.dll?func=ll&objId=888888&objAction=browse&viewType=1";
// Create an instance of WebClient
WebClient client = new WebClient();
client.Proxy = null;
client.Credentials = new System.Net.NetworkCredential(username, password, domain);
client.DownloadFile(new Uri(url), #"C:\FileDownloads\test.txt");
Attempt 2:
string username = "username";
string password = "password";
string domain = "domain";
string url = #"http://LiveLinkInstance.com/livelink/llisapi.dll/999999/WordDocument.docx?func=doc.Fetch&nodeid=999999&ReadOnly=True&VerNum=-2&nexturl=/livelink/llisapi.dll?func=ll&objId=888888&objAction=browse&viewType=1";
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(domain + "\\" + username + ":" + password));
wr.Headers.Add("Authorization", "Basic " + credentials);
CredentialCache cc = new CredentialCache();
cc.Add(new Uri(url), "NTLM", new NetworkCredential(username, password, domain));
wr.Credentials = cc;
Stream str = ws.GetResponseStream();

As Amitay said, using fiddler to compare against traffic from browser is the best way to go. BTW, look here on SO - what's happening is OP's case was that request was getting redirected to different location but credentials were not re-passed. So OP did manual redirection to solve the issue.

Did you try
client.UseDefaultCredentials = true
if you are using MVC or WebApi you should decorate your method with
[Authorize]
If you are able to impersonate a user, use it like this
WindowsIdentity wi = null;
wi = (WindowsIdentity)HttpContext.Current.User.Identity;
using (wi.Impersonate())
{
var client = new WebClient { UseDefaultCredentials = true };
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
var result = JsonConvert.DeserializeObject<Object>(Encoding.UTF8.GetString(client.DownloadData("http://api.com/api/values")));
return Request.CreateResponse(result);
}

I saw LL using its own form-based authentication or SSO based on IWA. I don't know if you can use other HTTP authentication types.
If your server uses the (default) form authentication you would have to use LAPI or WS to download the document providig the LL credentials within the LAPI/WS call. You could also just get a cookie for HTTP communication by LAPI/WS.
If you have SSO configured you can set Credentials to CredentialCache.DefaultCredentials to pass in credentials of the currently authentified Windows session.

Related

Does CredentialCache.DefaultCredentials always return current user's credentials?

I'm writing a C# app that is supposed to pass current user's credentials (Domain, Username and Password) to WebClient. For some reason the web service returns error 401 - Unauthorized even though I know for a fact, that credential of Window's user that is accessing it are the same as in the web service I'm trying to connect to.
var wc = new WebClient();
string jsonbefore = "";
Uri uri = new Uri(ConnectionString);
wc.UseDefaultCredentials = true;
wc.Credentials = System.Net.CredentialCache.DefaultCredentials;
wc.Headers["Accept"] = "application/json;odata=nometadata";
System.IO.Stream response = wc.OpenRead(conn);
StreamReader reader = new StreamReader(response);
jsonbefore = reader.ReadToEnd();
response.Flush();
Are there any environment/system settings that are stopping credentials from flowing? I've read up something about EnvironmentPermission class, but I don't know whether it's relatable to my problem.
Are there any better, more consistent ways of passing Windows credentials to a web service? Or is there any way to check if the username, password or domain from DefaultCredentials is being passed as null?

Check credential before requesting the Web Service

For a WebService, How can I check the credential before requesting the WebService?
In this exemple we are using a bad password to simulate a HTTP 401 : Unauthorized..
Is there a way before the var param = DoComplexeWork(); to validate the credential?
string UserName = "FOOBAR_USR";
string SecurelyStroredPassword = "FOOBAR_BAD_PWD";
string Domain = "FOOBAR_DOM";
string Url = "https://example.com/Foo/Bar.svc";
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(
new Uri(Url),
"Basic",
new NetworkCredential(UserName, SecurelyStroredPassword, Domain)
);
var iFoo = new MyFooBarWebService();
iFoo.Credentials = credentialCache;
//Check if Credential is OK
var param = DoComplexeWork();
var result = iFoo.CreateBar(param);
Validating the credentials are made on each request. So you need another URL to request that only validates the credentials.
Depending on your webservice you might be able to make a HEAD request. But that may or may not trigger the actual processing as well.
So there is no obvious easy way to do this, because of the underlying HTTP protocol.

Cannot connect to url in C# with 401 unauthorized error

I'm looking to get the content of a page from
http://12.18.60.199:81
I'm using my corporate network and if I use internet explorer, it prompts for username and password, I type that in and I get the content of the page. I need to do this in C#, but have no luck for the past few hours:
Uri requestUri = null;
Uri.TryCreate("http://12.18.60.199:81", UriKind.Absolute, out requestUri);
NetworkCredential nc = new NetworkCredential(#"username", #"password", "domain");
CredentialCache cache = new CredentialCache();
cache.Add(requestUri, "Basic", nc); //also tried "Anonymous", "Basic", "Digest", "Dpa",
//"External", "Kerberos", "Msn", "Negotiate", "Ntlm", "Sicily"
using (WebClient client = new WebClient())
{
client.Credentials = cache;
using (Stream stream = client.OpenRead("http://12.18.60.199:81"))
using (StreamReader reader = new StreamReader(stream))
{
//stuff
}
}
Keep getting 401 unauthorized, invalid credentials, help!
If I substitute the above address with http://google.com, it'll work, so the code works... username and password have been tested to work in broswer
If you are connecting through a proxy server try adding in your proxy and pass the credentials. For example:
// Prepare web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create("http://www.test.com");
// proxy details
myRequest.Proxy = new WebProxy("http://10.0.0.1", true);
myRequest.Proxy.Credentials = new NetworkCredential("test", "password", "domain");
I had same issue, and found workaround to add Authorization request header. I've used fiddler to get that base64. Never found proper solution, as you all know temp solutions are long-lasting in out world :)
service.Url = "http://127.0.0.1/";
service.SetRequestHeader("Authorization", "Basic dW8sX3NvYXB6SjRma2pzdXZqNDg5ZA==");
service.PreAuthenticate = true;

Download file using System.Net.WebClient for pages with form based logins

I am trying to download a file from a microsoft site, that uses form based logins (microsoft account). How can I do that using WebClient ?
The link is something like "http://go.microsoft.com/fwlink/ ....."
Thanks
You can set credentials to the WebRequest as follows. This post explains how to download the file.
// Create a request for the specified remote file name
WebRequest request = WebRequest.Create(remoteFilename);
if (request != null)
{
string username = "username";
string password = "password";
request.Credentials = new System.Net.NetworkCredential(username, password);
}

Use Kerberos-ticket in C# client application

I have a web-application where I'm automatically logged in with my Windows Credentials.
I now want to consume information from this web-application, in a c# windows application using my Windows Account. Therefore I need to be able to get the session-cookie from this web-site.
Here you can see a piece of my code, where I want to retrieve the cookie :
string URLAuth = extractParameterFromProperties("relatieBeheer_login_url");
WebClient webClient = new WebClient();
webClient.Credentials = CredentialCache.DefaultCredentials;
// webClient.UseDefaultCredentials = true;
byte[] responseBytes = webClient.DownloadData(URLAuth);
//byte[] responseBytes = webClient.UploadValues(URLAuth, "POST", formData);
string resultAuthTicket = Encoding.UTF8.GetString(responseBytes);
if(resultAuthTicket.Contains("Verkeerde combinatie gebruikersnaam")){
sessionCookie="NoSession";
}else{
WebHeaderCollection cookies = webClient.ResponseHeaders;
sessionCookie = cookies[HttpResponseHeader.SetCookie];
}
When I debug the application, I can see nothing is filled in the credentials :
Domain, Username & Password are empty.
Any help would be most welcome.
The ICredentials instance returned by DefaultCredentials cannot be used to view the user name, password, or domain of the current security context.
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultcredentials.aspx

Categories

Resources