154

I'm trying to go through an authentication request that mimics the "basic auth request" we're used to seeing when setting up IIS for this behavior.

The URL is: https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2
(warning: https!)

This server is running under UNIX and Java as application server.

This is the code I use to connect to this server:

CookieContainer myContainer = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2");
request.Credentials = new NetworkCredential(xxx,xxx);
request.CookieContainer = myContainer;
request.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

(I copied this from another post on this site). But I receive this answer from the server:

The underlying connection was closed: An unexpected error occurred on a send.

I think I tried every possible task my knowledge on C# has to offer me, but nothing...

CharithJ
  • 42,659
  • 20
  • 104
  • 124
Kenny Rullo
  • 2,157
  • 2
  • 14
  • 7

10 Answers10

306

You can also just add the authorization header yourself.

Just make the name "Authorization" and the value "Basic BASE64({USERNAME:PASSWORD})"

var username   = "abc";
var password   = "123";
string encoded = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1")
                               .GetBytes(username + ":" + password));
httpWebRequest.Headers.Add("Authorization", "Basic " + encoded);

Edit

Switched the encoding from UTF-8 to ISO 8859-1 per What encoding should I use for HTTP Basic Authentication? and Jeroen's comment.

ΩmegaMan
  • 22,885
  • 8
  • 76
  • 94
Zambonilli
  • 3,549
  • 1
  • 13
  • 17
  • 3
    So how do you know for sure that UTF8 is the right encoding to use? – Jeroen Wiert Pluimers Sep 20 '14 at 07:15
  • 2
    Nice catch. It looks like the request Authentication header should be encoded in ISO-8859-1. Per http://stackoverflow.com/questions/7242316/what-encoding-should-i-use-for-http-basic-authentication – Zambonilli Sep 21 '14 at 16:14
  • 1
    Aaaargh! 1: Thanks, mate. 2. I'd really like to understand why the other methods, setting the authentication method in the CredentialCache, wouldn't work at all. They are supposed to, aren't they? – mshthn Jul 28 '17 at 16:11
  • 1
    All the msdn documentation points to yes, the other methods should work. However, I've never been able to get them to work. – Zambonilli Aug 04 '17 at 12:46
  • Not working for me (neither utf-8 nor ISO-8859-1). Any suggestions what to check ? It works when I do " webRequest.Credentials = new NetworkCredential(UserID, Password);" . – RollerCosta Jun 24 '19 at 05:29
60

I finally got it!

string url = @"https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2";
WebRequest request = WebRequest.Create(url);
request.Credentials = GetCredential();
request.PreAuthenticate = true;

and this is GetCredential()

private CredentialCache GetCredential()
{
    string url = @"https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2";
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
    CredentialCache credentialCache = new CredentialCache();
    credentialCache.Add(new System.Uri(url), "Basic", new NetworkCredential(ConfigurationManager.AppSettings["ead_username"], ConfigurationManager.AppSettings["ead_password"]));
    return credentialCache;
}

YAY!

David d C e Freitas
  • 7,146
  • 4
  • 54
  • 66
Kenny Rullo
  • 2,157
  • 2
  • 14
  • 7
30

If you can use the WebClient class, using basic authentication becomes simple:

var client = new WebClient {Credentials = new NetworkCredential("user_name", "password")};
var response = client.DownloadString("https://telematicoprova.agenziadogane.it/TelematicoServiziDiUtilitaWeb/ServiziDiUtilitaAutServlet?UC=22&SC=1&ST=2");
Tamir
  • 3,525
  • 3
  • 28
  • 41
10

Try this:

System.Net.CredentialCache credentialCache = new System.Net.CredentialCache(); 
credentialCache.Add(
    new System.Uri("http://www.yoururl.com/"),
    "Basic", 
    new System.Net.NetworkCredential("username", "password")
);

...
...

httpWebRequest.Credentials = credentialCache; 
MrEyes
  • 11,483
  • 9
  • 44
  • 66
  • Is it definately basic auth? Also, can you access the resource with your username/password via a browser? – MrEyes Dec 02 '10 at 14:14
  • It seems to be a basic auth over https. If you click on the link i provided, the browser pop ups the username/password" request as the same do when you do "basic auth" on IIS or using a .htaccss file on a folder via apache. I tried to use fiddler but i have no clue about. – Kenny Rullo Dec 02 '10 at 15:56
  • i just learned that the website is running under IBM http server. This can be a helpful news? – Kenny Rullo Dec 02 '10 at 19:00
6

For those using RestSharp, it might fail when using SimpleAuthenticator (possibly due to not using ISO-8859-1 behind the scene). I managed to get it done by explicitly sending Basic Authentication headers:

string username = "...";
string password = "...";

public IRestResponse GetResponse(string url, Method method = Method.GET)
{
    string encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes($"{username}:{password}"));
    var client = new RestClient(url);
    var request = new RestRequest(method );
    request.AddHeader("Authorization", $"Basic {encoded}");
    IRestResponse response = client.Execute(request);
    return response;
}

var response = GetResponse(url);
txtResult.Text = response.Content;
Alexei - check Codidact
  • 17,850
  • 12
  • 118
  • 126
4

First thing, for me ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 worked instead of Ssl3.

Secondly, I had to send the Basic Auth request along with some data (form-urlencoded). Here is the complete sample which worked for me perfectly, after trying many solutions.

Disclaimer: The code below is a mixture of solutions found on this link and some other stackoverflow links, thanks for the useful information.

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        String username = "user_name";
        String password = "password";
        String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));

        //Form Data
        var formData = "var1=val1&var2=val2";
        var encodedFormData = Encoding.ASCII.GetBytes(formData);

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("THE_URL");
        request.ContentType = "application/x-www-form-urlencoded";
        request.Method = "POST";
        request.ContentLength = encodedFormData.Length;
        request.Headers.Add("Authorization", "Basic " + encoded);
        request.PreAuthenticate = true;

        using (var stream = request.GetRequestStream())
        {
            stream.Write(encodedFormData, 0, encodedFormData.Length);
        }

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
Jiten
  • 305
  • 2
  • 5
3

Following code will solve json response if there Basic Authentication and Proxy implemented.Also IIS 7.5 Hosting Problm will resolve.

public string HttpGetByWebRequ(string uri, string username, string password)
{
//For Basic Authentication
    string authInfo = username + ":" + password;
    authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));

//For Proxy
    WebProxy proxy = new WebProxy("http://10.127.0.1:8080", true);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "GET";
    request.Accept = "application/json; charset=utf-8";
    request.Proxy = proxy;

    request.Headers["Authorization"] = "Basic " + authInfo;

    var response = (HttpWebResponse)request.GetResponse();

    string strResponse = "";
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
        strResponse= sr.ReadToEnd();

    }

    return strResponse;
}
Mahabubuzzaman
  • 319
  • 3
  • 3
  • Not working for me (neither utf-8 nor ISO-8859-1 nor default). Any suggestions what to check ?Please note - It works when I do " webRequest.Credentials = new NetworkCredential(UserID, Password);" – RollerCosta Jun 24 '19 at 05:58
2

The spec can be read as "ISO-8859-1" or "undefined". Your choice. It's known that many servers use ISO-8859-1 (like it or not) and will fail when you send something else.

For more information and a proposal to fix the situation, see http://greenbytes.de/tech/webdav/draft-reschke-basicauth-enc-latest.html

Slan
  • 527
  • 6
  • 17
1

The following construction was not working correctly for me:

request.Credentials = new NetworkCredential("user", "pass");

I have used CredentialCache instead:

CredentialCache credentialCache = new CredentialCache
{
    {
        new Uri($"http://{request.Host}/"), "Basic",
        new NetworkCredential("user", "pass")
    }
};
request.Credentials = credentialCache;

However, if you would like to add multiple basic auth credentials (for example if there is redirection that you are aware of) you can use following function that I have made:

private void SetNetworkCredential(Uri uriPrefix, string authType, NetworkCredential credential)
{
    if (request.Credentials == null)
    {
        request.Credentials = new CredentialCache();
    }

    if (request.Credentials.GetCredential(uriPrefix, authType) == null)
    {
        (request.Credentials as CredentialCache).Add(uriPrefix, authType, credential);
    }
}

I hope it will help somebody in the future.

Gucu112
  • 511
  • 4
  • 7
0

One reason why the top answer and others wont work for you is because it is missing a critical line. (note many API manuals leave out this necessity)

request.PreAuthenticate = true;
desertnaut
  • 46,107
  • 19
  • 109
  • 140