I'm using this code to connect to a third party server.
using (HttpClientHandler httpClientHandler = new HttpClientHandler())
{
httpClientHandler.AllowAutoRedirect = false;
httpClientHandler.Credentials = new NetworkCredential(login, password);
using (HttpClient authClient = new HttpClient(httpClientHandler))
{
response = await authClient.GetAsync(authenticationUrl).ConfigureAwait(false);
... response processing here
}
}
The third party server is an appliance, and they've turned on NTLM recently. Starting with the turning on of NTLM, my request now gets an HTTP 500 error error like this:
type Exception report message NTLM specified. Downgraded to Basic
Auth (and/or SSL) but downgrade not supported. description The server
encountered an internal error that prevented it from fulfilling this
request. exception java.lang.UnsupportedOperationException: NTLM
specified. Downgraded to Basic Auth (and/or SSL) but downgrade not
supported.
net.sourceforge.spnego.SpnegoProvider.negotiate(SpnegoProvider.java:146)
net.sourceforge.spnego.SpnegoAuthenticator.authenticate(SpnegoAuthenticator.java:271)
net.sourceforge.spnego.SpnegoHttpFilter.doFilter(SpnegoHttpFilter.java:229)
I'm assuming my httpclient sees that the server now supports NTLM and tries to do NTLM. Is there any way to tell my httpclient to don't even bother with NTLM?
To disable NTLM try this:
var modules = AuthenticationManager.RegisteredModules;
while (modules.MoveNext())
{
var module = (IAuthenticationModule) modules.Current;
if (module.AuthenticationType == "NTLM")
{
AuthenticationManager.Unregister(module);
break;
}
}
Related
I am trying to validate URL in C# code and I am facing error on Windows server 2012R2 server machine
The request was aborted: Could not create SSL/TLS secure channel
I have checked the multiple solutions found/got via various posts in net and nothing resolved this.
C# code
public static bool isBrokenLink(string url, string KBid)
{
Boolean isBrokenLink = false;
try
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);
webRequest.CookieContainer = new CookieContainer();
webRequest.AllowAutoRedirect = false;
webRequest.Timeout = 40000;
using (HttpWebResponse httpresponse = (HttpWebResponse)webRequest.GetResponse())
{
if (httpresponse.StatusCode == HttpStatusCode.OK)
{
isBrokenLink = false;
}
else if (httpresponse.StatusCode >= HttpStatusCode.Ambiguous && httpresponse.StatusCode <= HttpStatusCode.RedirectKeepVerb)
{
isBrokenLink = false;
}
else
{
isBrokenLink = true;
}
}
}
catch (Exception ex)
{
isBrokenLink = true;
}
return isBrokenLink;
}
On the machine, I have installed both IE and Chrome browser. When I trying to load the URL in IE 11 browser, I am getting the same error.
When trying to check in the chrome browser with the URL, it works fine. I also tried to set the default browser as chrome in my machine and checked. But still the same issue. Does anybody know about this issue?
Can we modify the code to consider the chrome browser for HttpWebResponse validation?
There can be many reasons for this kind of error and the provided details are not sufficient. Typical problems are with validating certificates or with TLS versions or with supported ciphers etc.
In general: your C# code and IE use the same TLS stack built into Windows while Chrome comes with its own TLS stack (BoringSSL). Setting Chrome is default browser will not magically replace the OS TLS stack, i.e. it will still only used by Chrome and not your C# program.
If the URL is public you can use SSLLabs to get more information about this site which also displays typical problems and compatibility with various kind of clients. This might help you to narrow down the problem yourself.
I'm trying to invoke rest method with asp.net core 2.1 but keep getting the ssl exception even I'm using a http in this call. The code that im using is:
public async Task<bool> SyncTickets()
{
try
{
HttpClient client = new HttpClient();
var path = "http://testdesk.vmw.be:8082/helpdesk/WebObjects/Helpdesk.woa/ra/PriorityTypes?username=admin&apiKey=bJZw2jP8wgtyGXI736K6DfUiEjJYTLuqC8fGuOBN";
Ticket ticket = new Ticket();
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var responseMsg = await response.Content.ReadAsAsync<Object>();
return true;
}
return false;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return false;
}
Exception is:
{System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException: The handshake failed due to an unexpected packet format
Exception occur on GetAsync method.
When I'm using the same path to test trough postman or browser it's working perfectly fine, I'm getting the response.
Any idea what I'm missing here?
Maybe your server requires encryption anyway and redirects to https?
If that's the case and https still reports add before creating HttpClient:
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
This will accept all certs. This setting is global to your app. DO NOT USE IT IN PRODUCTION. If your server uses selfsigned cert or internal CA issued cert use it only for testing. In production add proper validation of internal CA or accept only specific self-signed cert. Browsers might have internal certs or CAs added on PC's from domain controller or via group policy and therefore they don't report them untrusted.
Also, for https you can explicitly use TLS protocols. Add the following line before creating HttpClient and try again:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
If you have defined protocol set at your server, you can narrow down protocol list just to enable those actually supported.
I'm trying to connect through a https proxy but an exception is always caught stating that "The ServicePointManager does not support proxies of https scheme".
The code I'm using to test the connection is the following one :
var handler = new HttpClientHandler
{
UseProxy = true,
Proxy = new WebProxy("https://xxx.xxx.xxx.xxx:443") {Credentials = new NetworkCredential(Username, Password)}
};
using (var client = new HttpClient(handler))
{
var x = await client.GetStringAsync("https://api.ipify.org/?format=text");
}
I also tested the proxy using curl and it worked perfectly (although I had to use --proxy-insecure for some reason). The command I used is :
curl --proxy-insecure -x https://username:password#xxx.xxx.xxx.xxx:443 https://api.ipify.org/?format=text
When I tried using http:// for the proxy curl just gave me the error "(56) Proxy CONNECT aborted".
So, is it possible to use a https proxy with the .NET Framework ? (I'm currently using .NET 4.6.2)
I have an asp.net MVC 4 Web API that was created in VS2010. It is currently hosted on a Windows Server 2003 box running IIS 6.0. The API works great when I navigate to it using Google Chrome from my machine (on the same network as the server). The issue I am having is when I try to consume the API from a VS2013 C# console app. I am getting the following response:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{ Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Mon, 04 Apr 2016 16:09:50 GMT
Content-Length: 1539
Content-Type: text/html
}}
Here is the code for the console app:
static void Main(string[] args) {
RunAsync().Wait();
Console.ReadLine();
}
static async Task RunAsync() {
using (var client = new HttpClient()) {
client.BaseAddress = new Uri("http://server/website/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/rateshop/1000/03/90210/");
if (response.IsSuccessStatusCode) {
RatingResultModel rateResults = await response.Content.ReadAsAsync<RatingResultModel>();
foreach (var rate in rateResults.Rates) {
Console.WriteLine("{0}\t${1}", rate.Service, rate.Rate);
}
} else {
Console.WriteLine("{0}\n{1}", response.StatusCode, response.RequestMessage);
}
}
}
My actual WebAPI has [AllowAnonymous] above the ApiController.
The IIS 6.0 server has Anonymous Authentication enabled, and the current user is set to the server administrator, and I provided full control to the website directory for the administrator. Integrated Windows Authentication is also enabled.
So far everything I have searched for is either documentation on how to "Return a 401 status code" instead of what to do when a 401 status code is returned, or it is documentation on how to add authentication to a Web API instead of how to remove it. There seems to be very little on how to handle a Web API in IIS 6.0. As far as I can tell, anonymous authentication is enabled.
I have already tried this stackoverflow answer and I've followed MSDN's article on adding anonymous access to IIS 6.0. I don't believe I will need authentication or authorization security for this Web API since it is going to be used on a local network.
Given that the API works when I consume it with Google Chrome from my machine, what might be causing my issue with trying to use a console app to consume the Web API?
Thanks to #Nilesh for the answer.
Wrapping my RunAsync method in a using (var clientHandler = new HttpClientHandler() {UseDefaultCredentials = true}) did the trick.
Full solution:
using (var clientHandler = new HttpClientHandler()) {
clientHandler.UseDefaultCredentials = true;
using (var client = new HttpClient(clientHandler)) {
client.BaseAddress = new Uri("http://server/website/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/rateshop/1000/03/90210/");
if (response.IsSuccessStatusCode) {
RatingResultModel rateResults = await response.Content.ReadAsAsync<RatingResultModel>();
foreach (var rate in rateResults.Rates) {
Console.WriteLine("{0}\t${1}", rate.Service, rate.Rate);
}
} else {
Console.WriteLine("{0}\n{1}", response.StatusCode, response.RequestMessage);
}
}
}
i am just working on my first Windows Phone 8.1 app (Universal if this matters, but only Windows Phone implemented at the moment). And at first all is working very smooth but as soon as my app is running for about 25-30 Minutes I can no longer use my HttpClient. I use the Windows.Web.Http.HttpClient.
In my first trys I used a singleHttpClientand reused it all the time. As I became aware that this is not working I started using a newHttpClient` for each request. But still no luck.
This is my method to get a new HttpClient:
private HttpClient GetClient()
{
var filter = new HttpBaseProtocolFilter
{
AllowUI = false,
CacheControl = { WriteBehavior = HttpCacheWriteBehavior.NoCache },
ServerCredential =
new PasswordCredential(
BaseApiUri.ToString(),
credentials.UserName,
credentials.Password),
};
var httpClient = new HttpClient(filter);
var headers = httpClient.DefaultRequestHeaders;
var httpConnectionOptionHeaderValueCollection = headers.Connection;
httpConnectionOptionHeaderValueCollection.Clear();
headers.Accept.TryParseAdd("application/json");
headers.CacheControl.TryParseAdd("no-cache");
headers.Add("Pragma", "no-cache");
headers.Add("Keep-Alive", "false");
headers.Cookie.Clear();
return httpClient;
}
The extra code setting the headers and clearing cookies are my attempts to stop some kind of caching of connections under the surface that might happen. But still no luck.
My method to make requests my API is like the following:
private async Task<bool> PostNoResponseRequestTo(string relativeUri, object requestContent, CancellationToken cancellationToken)
{
var targetUri = new Uri(BaseApiUri, relativeUri);
var requestJson = JsonConvert.SerializeObject(requestContent);
var content = new HttpStringContent(requestJson, UnicodeEncoding.Utf8, "application/json");
try
{
using (var httpClient = this.GetClient())
{
var post =
await httpClient.PostAsync(targetUri, content).AsTask(cancellationToken).ContinueWith(
async request =>
{
using (var response = await request)
{
return response.IsSuccessStatusCode;
}
},
cancellationToken);
return await post;
}
}
catch (Exception)
{
return false;
}
}
This works fine for about 25-30 Minutes after which the calls to the api suddenly start to fail. I start getting a 401 but as you can see i have specified credentials and because those are working and do not change (hardcoded them to test this) i start believing that the problem is on the API side.
This is the response I get:
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 2, Content: Windows.Web.Http.HttpStreamContent, Headers:
{
Server: Microsoft-IIS/8.5
Date: Fri, 20 Mar 2015 14:25:06 GMT
WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+NounceRemoved",charset=utf-8,realm="Digest", Negotiate, NTLM
X-Powered-By: ASP.NET
}
{
Content-Length: 1344
Content-Type: text/html
}
My API consists of a Asp.Net project with ServiceStack for its API functionality.
This is running on an IIS with activated digest authentication (all other are disabled).
By inspecting the logs i became aware of a failing API call in front of each successful call. But if i'm right this is by design of digest auth because i have not found a way to tell the client that the other side is using digest auth. I was able to specify this kind of information in my other .Net projects but for some reason Microsoft changed the code (and namespace) for the HttpClient. I am also aware of the HttpClient in the original namespace that you can get through nuget but this is not working for me as i get an error in my output window as soon as i make any call. This closes my app without any kind of information.
Back to the log i was able to get some information with the help of the extended logging and the tool to analyze them. The error is something like (can't access it right now will edit it later):'Invalid token passed to function/method'.
I really hope that someone can help me to solve this problem as it makes the app nearly unusable. My users have to restart the app every 15 Minutes to be on the save site.
Thanks for all advices that help me.
Try Checking the Machine Key setting in IIS. Automatically generate at runtime if tick will generate a new key every time the app pool is restarted. This might be causing your issue. The Machine Key can be set on the server, website or application level. As activated digest authentication is encrypted this might be the issue.
Managing Websites with IIS Manager (part 6) - The Machine Key and Windows Authentication