System.Net.CredentialCache and HttpWebResponse - c#

I'm trying coding some functionality where the user may log in into a remote server by using its own Windows Credentials or by specifying some user, password and domain.
In order to know how to do it I read this link[1].
I have been able to successfully log in via CredentialCache.DefaultCredentials.
However, whenever I try to authenticate via user, name, password and domain I keep on getting a 401 error.
After some Googling and searching here I have found some probable errors (redirecting, different auth. types {basic, digest, ntlm, negotiate} and even the case contrary [i.e. being able to login through user+pasword but no by CredentialCache.DefaultCredentials]).
Any hints?
Edit: maybe some code would give you some clues about what I am doing wrong.
static void Main(string[] args)
{
string password = "password", username = "Username", dom = "DOMAIN";
string url = "http://my.url.com/LoginWithNativeCredentials?";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
/////// Different User code////
NetworkCredential credentials = new NetworkCredential(username, password, dom);
CredentialCache cache = new CredentialCache();
cache.Add(new Uri(url), "NTLM", credentials);
request.Credentials = cache;
/////////////////////////
////// Current Windows user's credential
//request.Credentials = CredentialCache.DefaultCredentials;
/////////////////////////
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer(5);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine("In!");
}
Console.WriteLine("Done!");
Console.ReadLine();
}
Many thanks!
[1] http://support.microsoft.com/kb/811318

Related

Cannot send authentication in header of project

So basically I'm working on integrating a web API into my project from an externally hosted source.. But the xml is stored behind basic authentication. So I've been advised that I need to parse some authentication into the header of my HTTP request when contacting the location of the XML.
Here's what I'm working with at the moment:
I've created a controller, my code is as follows:
namespace com.tortoise.Controllers
{
public class VebraController : ApiController
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("url");
string username = "user";
string password = "password";
string usernamePassword = ("username + : + password");
CredentialCache cache = new CredentialCache();
new cache.add Uri(url), "Basic", new class NetworkCredential(username, password));
request.Credentials = cache;
request.Headers.Add("Authorization", "Basic " // <- space here.
+ Convert.ToBase64String()(new Int64 ASCIIEncoding().GetBytes (usernamePassword));
// Get the token from the response:
string token = response.GetResponseHeader("Token");
}
Any help is great. I'm receiving errors in CredentialCache, ASCIIEncoding, ToBase64String(), GetBytes() and GetResponseHeader().
Alright, I have fixed your code a bit. It should compile now, assuming you have actually declared the variables you are using. I can't do that for you. Please read the comments. You seem to need a lot of practice with C# syntax and the language in general, you had a lot of invalid C# in there. Hope this helps.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
string username = "user";
string password = "password";
//here I am declaring the NetworkCredentials. You do not need to put 'new class'
NetworkCredential myCredentials = new System.Net.NetworkCredential(username,password);
string usernamePassword = (username + password); //I assume you meant to concatenate them
CredentialCache cache = new CredentialCache();
cache.Add((Uri)url, "Basic", myCredentials); //you must declare url, not sure what you want it to be
request.Credentials = cache;
request.Headers.Add("Authorization", "Basic " // <- space here.
+ Convert.ToBase64String(Encoding.ASCII.GetBytes(usernamePassword)); //fixed this
// Get the token from the response:
string token = response.GetResponseHeader("Token"); //you need to declare response somewhere

HttpWebRequest Credentials stored/cached automatically?

I have an HttpWebRequest with Credentials, as seen below. This works perfectly well. However, something strange happens when I change my password on the server side: subsequent requests to the same URL are successful, even though the password is no longer valid.
This behavior continues even if I close the app completely and reopen it. Do the Credentials persist somehow? Any insight would be greatly appreciated.
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(item.Url) as HttpWebRequest;
nc = new NetworkCredential();
nc.UserName = Username;
nc.Password = Password;
request.Credentials = nc;
request.BeginGetResponse(new AsyncCallback(SubReadWebRequestCallback), request);
}

NetworkCredential working for POST but not GET

I'm calling a webAPI web service that uses windows authentication. I'm using this code in my development environment since I am developing from a box that is not on the domain.
var req = (HttpWebRequest)WebRequest.Create(url);
req.Credentials = new NetworkCredential("username", "password", "domain");
req.Method = WebRequestMethods.Http.Post; //or get
This works just fine when I do a post, but when I want to do a get it doesn't work.
When i visit the url for the get in a web browser it asks for my username and password, as expected. I enter the username and password correctly and the GET works.
Try basic authentication as below:
string credentials = String.Format("{0}:{1}", username, password);
byte[] bytes = Encoding.ASCII.GetBytes(credentials);
string base64 = Convert.ToBase64String(bytes);
string authorization = String.Concat("Basic ", base64);
req.Headers.Add("Authorization", authorization);

C#: Post login data to form and process website's response

I am trying to write a C# program to prolong the deadline for my books in my university's library. What I want to do is the following:
1.) Login to library website via WebRequest & POST method, with username & password entered in C# program
2.) Get the url to "View borrowed books" site containing the encrypted password & plain text username as GET parameters
3.) Download content of named page to display to user in the C# program
4.) If the user presses the corresponding button in the program, submit the prolongation form to the website to prolong all media at once.
Right now I'm stuck between 1 and 2, I seem to be able to connect to the website and to enter the userdata, but the WebResponse I get is again the login page (which is not the case if you login manually on the website).
This is the method I wrote to connect to the website:
// Login function, logs the user in, uses passed user number & password
public static Boolean userLogin(String unr, String pass)
{
// Login
// Cookie needed for maintaining php session
CookieContainer cContainer = new CookieContainer();
Console.WriteLine(unr+","+pass);
String postUrl = "https://universitylibrary.com/loan/DB=4/LNG=DU/USERINFO_LOGIN";
String formParams = String.Format("ACT={0}&HOST_NAME={1}&HOST_PORT={2}&HOST_SCRIPT={3}&LOGIN={4}&STATUS={5}&BOR_U={6}&BOR_PW={7}","UI_DATA","","","","KNOWNUSER","HML_OK", unr, pass);
String cookieHeader;
WebRequest wreq = WebRequest.Create(postUrl);
wreq.ContentType = "application/x-www-form-urlencoded";
wreq.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
wreq.ContentLength = bytes.Length;
using (Stream os = wreq.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = wreq.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
//Authentication trial
String PageSource;
String getUrl = "https://universitylibrary.com:443/loan/DB=4/USERINFO";
WebRequest getReq = WebRequest.Create(getUrl);
getReq.Headers.Add("Cookie",cookieHeader);
WebResponse getResp = getReq.GetResponse();
using (StreamReader sr = new StreamReader(getResp.GetResponseStream()))
{
PageSource = sr.ReadToEnd();
}
Console.Write(PageSource);
return true;
}
Can you see my mistake? I get the sourcecode and the params (username, password) output on the console, but the output is again the login page.
I would just look at the php page, but I don't have access to any of the internal system data, all I have is the HTML page.
Any suggestions would be highly appreciated!
EDIT:
I have rethought the whole thing, and rebuilt the HTTP request header completely as recorded by fiddler. That part of the function looks like this now:
// Login
// Cookie needed for maintaining php session
CookieContainer cContainer = new CookieContainer();
HttpCookie cookie = new HttpCookie("cookie", "PSC_4='xxxxxxx'; DB='n'");
CookieCollection cookieCol = new CookieCollection();
cookieCol.Add(cookieCol);
cContainer.Add(cookieCol);
Console.WriteLine(unr+","+pass);
String postUrl = "https://universitylibrary.com:443/loan/DB=4/USERINFO";
String formParams = String.Format("ACT={0}&HOST_NAME={1}&HOST_PORT={2}&HOST_SCRIPT={3}&LOGIN={4}&STATUS={5}&BOR_U={6}&BOR_PW={7}","UI_DATA","","","","KNOWNUSER","HML_OK", unr, pass);
String cookieHeader;
HttpWebRequest wreq = (HttpWebRequest) WebRequest.Create(postUrl);
wreq.Referer = "https://universitylibrary.com/loan/DB=4/LNG=DU/USERINFO_LOGIN";
wreq.KeepAlive = true;
wreq.ContentLength = 119;
wreq.Host = "universitylibrary.com";
wreq.ContentType = "application/x-www-form-urlencoded";
wreq.Method = "POST";
wreq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0";
wreq.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
wreq.SendChunked = true;
wreq.TransferEncoding = "gzip, deflate";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
wreq.ContentLength = bytes.Length;
using (Stream os = wreq.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
cookieHeader = "";
try
{
HttpWebResponse resp = (HttpWebResponse) wreq.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
}
catch (WebException ex)
{
Console.WriteLine(ex.Status);
Console.WriteLine(ex.Response);
}
The whole thing still doesn't work though, same issue as before.
Is it possible that HttpWebRequest can't handle https or that something else is missing for https to work? (HTTP & HTTPS seem to be syntactically identical and the port is correctly set to 443, the real difference seems to lay in the additional SSL/TLS layer, maybe I need to add this somewhere?)
When you are returned the login page it probably means that you have not been correctly authenticated. There could be several reasons for this, but in the end it is because you not mirroring the HTTP communication from the manual login on the website correctly.
What I usually do is to use a monitor such as Fiddler to capture the full request/response pattern from the manual login, which I can then subsequently mirror in my code.
You can just modify your login page after checking login data and make the only output is "SuccessfullySignIn", for example.
If this is the data your receive,
$if (getReq == "SuccessfullySignIn")
{
//Do something
}
And try to use Redirect features in your webpage

C# SSL Basic Access Authentication

I want to request reports from a third party and they require "Basic Access Authentication" via POST:
Your client application must use Basic Access Authentication
to send the user name and password.
Can someone point me in the right direction?
Edit: I did see this post but there are two answers and I'm not sure if thats what I need to do or which one is the preferred method.
Assuming you use a WebRequest, you attach a CredentialCache to your request:
NetworkCredential nc = new NetworkCredential("user", "password");
CredentialCache cc = new CredentialCache();
cc.Add("www.site.com", 443, "Basic", nc);
WebRequest request = WebRequest.Create("https://www.site.com");
request.Credentials = cc;
request.PreAuthenticate = true;
request.Method = "POST";
// fill in other request properties here, like content
WebResponse respose = request.GetResponse();
The basic gist is like this:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = WebRequestMethods.Http.Get;
request.Credentials = new NetworkCredential(username, password);
but sometimes there are issues with using request credentials, the alternative is add the authentication data in request headers
string authInfo = username + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
for more details see this blog post
http://charlie.cu.cc/2012/05/how-use-basic-http-authentication-c-web-request/

Categories