Kenny Rullo
Kenny Rullo

Reputation: 2567

HttpWebRequest using Basic authentication

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...

Upvotes: 185

Views: 467785

Answers (11)

Caveman
Caveman

Reputation: 2955

Here's how to do a Http Basic Auth string in C#

string username = "user";
string password = "pass";            
var basicAuthBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes($"{username}:{password}");
var authHeaderValue = $"Basic {System.Convert.ToBase64String(basicAuthBytes)}";

Upvotes: 1

Zambonilli
Zambonilli

Reputation: 4591

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.

Upvotes: 370

Rick Drayson
Rick Drayson

Reputation: 29

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;

Upvotes: -1

1JD
1JD

Reputation: 325

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();

Upvotes: 6

Gucu112
Gucu112

Reputation: 957

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.

Upvotes: 1

Alexei - check Codidact
Alexei - check Codidact

Reputation: 23078

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;

Upvotes: 9

Mahabubuzzaman
Mahabubuzzaman

Reputation: 349

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;
}

Upvotes: 4

Slan
Slan

Reputation: 560

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

Upvotes: 2

Tamir
Tamir

Reputation: 3901

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");

Upvotes: 35

Kenny Rullo
Kenny Rullo

Reputation: 2567

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!

Upvotes: 70

MrEyes
MrEyes

Reputation: 13690

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; 

Upvotes: 12

Related Questions