401 Unauthorized only when on server - c#

Problem: This code works fine from my local machine, but NOT on the server itself. (E.G. I can run this Linqpad script from my machine, I get a 200 and some data. I copy it to the server where the app is hosted and I get a 401. Why!? App has Windows Auth only enabled, NTLM only.
//Create REST client
var client = new RestClient("https://app.com/service/")
{
//Windows Auth
Authenticator = new NtlmAuthenticator("test\\test", "9##903f")
};
//Create Request to be sent
var request = new RestRequest("api/dogs/furriest");
//Create params to send
var parameters = new {
FurryLevel = 1,
CuteLevel = 2
};
//Add params to request
request.AddParameter("application/json", parameters.ToJson(), ParameterType.RequestBody);
//Execute the request
var response = client.ExecuteAsPost(request, "POST");

Do you enable windows authentication on your IIS site ?

Related

HttpClient authorization error on linux machine

This is my simple spike code:
var url = "http://url.de";
var username = "user";
var password = "password";
var client = new HttpClient();
var base64 = Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64);
var result = client.GetAsync(url).Result;
On my Ubuntu server I always get a 401 authentication error with this code.
When I fire the webservice data on the same machine with Postman, the call works.
If I run the code directly on the webservice server (Windows Server) itself, the call works too.
What can be the problem?
Firewall is disabled.
I found the problem.
For whatever reason, the call via the code only works over HTTPS.

Http endpoint for IOT hub resource

How to get the http endpoint of an iot hub in azure. I need to build a solution to ping the http url to test whether iot hub is active or down. Similar to availability check.
So you can create an Azure Function or whatever you favor, to invoke this REST API to obtain the status. Example response will be like this
{
"totalDeviceCount": 0,
"enabledDeviceCount": 0,
"disabledDeviceCount": 0
}
To Authenticate against AZURE API you need to obtain the BEARER token first.
Example :
private const string Resource = "https://management.azure.com/";
string authority = $"https://login.windows.net/"TenantId";
var authContext = new AuthenticationContext(authority);
var credential = new ClientCredential("ClientId", "ClientSecret");
var authResult = authContext.AcquireTokenAsync(Resource, credential).Result;
var httpClient = new HttpClient();
Now when you call any azure resource api, pass the bearer token along
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + authResult.AccessToken);

Passing current authentication credentials from UWP app to web service to access resources on server with these credentials

My Windows 10 UWP app is calling a WebAPI web service that I have created. I need to pass the current credentials on the client side when calling the web service so that it can access other resources using these credentials.
I also need to do this without prompting the user for credentials so that the experience is seamless.
I am able to do this with using System.Net.Http and successfully pass the current credentials to the server to use for accessing resources. This sends the request and brings back the response without any prompt. I have enabled Enterprise Authentication and Private Networks capabilities on the UWP app to make this work.
Problem: This works fine for GET requests but not for POST requests to the same server. POST requests result in the following error:
This IRandomAccessStream does not support the GetInputStreamAt method
because it requires cloning and this stream does not support cloning.
I read that this was a bug on this link: PostAsync throwing IRandomAccessStream error when targeting windows 10 UWP. The workaround proposed in multiple locations for this bug is to use Windows.Web.Http instead. However, if I do this, how can I pass the default/current credentials to the server?
Here is the code that I am using to do a GET request using the current Windows credentials without prompting for it. It works flawlessly:
System.Net.Http.HttpClientHandler handler = new System.Net.Http.HttpClientHandler
{
UseDefaultCredentials = true
// Credentials = (NetworkCredential)System.Net.CredentialCache.DefaultNetworkCredentials
//using either one of the above enables me to have the web service use the current credentials without prompting
};
string responseContent = string.Empty;
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(handler))
{
System.Net.Http.HttpRequestMessage requestMessage = new System.Net.Http.HttpRequestMessage();
requestMessage = new System.Net.Http.HttpRequestMessage
{
Method = System.Net.Http.HttpMethod.Get,
RequestUri = new Uri(strWebServiceURL)
};
using (System.Net.Http.HttpResponseMessage response = await client.SendAsync(requestMessage))
{
responseContent = await response.Content.ReadAsStringAsync();
}
//This also works fine
using (System.Net.Http.HttpResponseMessage response = await client.GetAsync(strWebServiceURL))
{
responseContent = await response.Content.ReadAsStringAsync();
}
Below is the code I use to do a POST request which results in the IRandomAccessStream error:
System.Net.Http.HttpClientHandler handler = new System.Net.Http.HttpClientHandler
{
UseDefaultCredentials = true
// Credentials = (NetworkCredential)System.Net.CredentialCache.DefaultNetworkCredentials
//using either one of the above enables me to have the web service use the current credentials without prompting
};
string responseContent = string.Empty;
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(handler))
{
System.Net.Http.HttpRequestMessage requestMessage = new System.Net.Http.HttpRequestMessage();
requestMessage = new System.Net.Http.HttpRequestMessage
{
Content = myMultipartFormDataContent,
Method = System.Net.Http.HttpMethod.Post,
RequestUri = new Uri(strWebServiceURL)
};
using (System.Net.Http.HttpResponseMessage response = await client.SendAsync(requestMessage))
{
responseContent = await response.Content.ReadAsStringAsync();
}
//No difference when using it this way as well
using (System.Net.Http.HttpResponseMessage response = await client.PostAsync(strWebServiceURL, myMultipartFormDataContent))
{
responseContent = await response.Content.ReadAsStringAsync();
}
I tried using Windows.Web.Http but I don't know how I can get it to pass the current/default credentials to the server without prompting.
I have also added the WebService URL to a IE Local Intranet zone and have that zone set to automatically log in with current user name and password:
Please help!
With the new Windows.Web.Http namespace in UWP app, if you want to use the DefaultCredentials, all you have to do is turn on enterprise credentials in the manifest and the uwp app will send them out as appropriate. You don't need to configure anything on the HttpClientto make it work. Details please reference this thread.
Since you already enable the enterprise credentials capability, you could just create HttpClient without configure. But to avoid the username and password prompt, you may need to disable the UI, for example:
var myFilter = new HttpBaseProtocolFilter();
myFilter.AllowUI = false;
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient(myFilter);
Windows.Web.Http.HttpResponseMessage result = await client.GetAsync(new Uri("http://localhost:5132/api/values"));

Web API Call from a C# console application with credentials

I am trying to write a Web API site with a Get method that is Authorized. The site is a default template site, using Individual Accounts. So it stores the username and password in a database. I am attempting to call this Web API site and pass along a username and password in a console application via HttpClient. I have tried several ways of going about this. I think* i have CORS enabled on my API site. I keep getting Unauthorized results. Here is the HttpClient code I am running, I feel like it is completely valid, and I think something needs to be configured to handle this username and password on the API side, but I am completely unsure how to go about it if that is the case.
using (var client = new HttpClient())
{
var byteArray = Encoding.ASCII.GetBytes("sampleUser:Test123!");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.BaseAddress = new Uri("http://localhost:15198/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage response = await client.GetAsync("api/Query");
if (response.IsSuccessStatusCode)
{
thing = response.Content.ToString();
}
}
catch (HttpRequestException e)
{
var test = e.Message;
}
}
you would need to impersonate and pass the credentials assuming your running windows authentication on your server.
using (new Impersonator(UserName, Domain, Pwd))
{
...http request
}
See thread

Universal App NTLM working for Windows Store, but not Windows Phone

I am building a Universal App that accesses a web API for data.
When I run the authentication piece in the Windows Store app, everything works and I get a 200 response on my login call (an HTTP POST call to _url2 in the code below)
When I run the exact same code from the Windows Phone emulator, I get a 401 Unauthorized.
Here is the code I'm using to access the service:
var handler = new HttpClientHandler
{
AllowAutoRedirect = true,
PreAuthenticate = true,
CookieContainer = _cookies,
Credentials = new NetworkCredential(username, password),
UseCookies = true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
using (var client = new HttpClient(handler, true))
{
//client.DefaultRequestHeaders.Connection.Add("keep-alive");
// Having the Connection = keep-alive causes the phone to throw an exception... not needed, but annoying
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"));
var res = await client.GetAsync(_url1); // This works and will negotiate NTLM on both platforms. Returns 200 on both Phone and Store apps
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
client.DefaultRequestHeaders.Referrer = new Uri(_url1);
client.DefaultRequestHeaders.Add("Origin", _url1);
using (var message = new HttpRequestMessage(HttpMethod.Head, _url2))
{
var header = await client.SendAsync(message); // 401 on Phone, 200 on Store app
}
var resp = await client.PostAsync(_url2, new StringContent(LoginContent)); // 401 on Phone, 200 on Store app
using (var stream = await resp.Content.ReadAsStreamAsync())
using (var reader = new StreamReader(stream))
{
var html = await reader.ReadToEndAsync();
ParseLoginResults(html);
}
}
I think that when the client does something other than Get, it seems to not complete the NTLM handshake... I haven't been able to configure Fiddler to work with my emulator, so I haven't gotten a good trace on what is going on. The communication is all over HTTPS so I can't get anything useful over WireShark either.
Any idea why it works on Windows Store apps, but not on the phone? Are there any other work arounds for NTLM authentication? Can I just do everything manually?
it´s far from completed but you could try this :
http://uwapi.codeplex.com/
However...as far as i know windows phone emulator does not allow https connections to localhost. maybe that´s your problem. You need to add a certificate to allow https traffic.

Categories

Resources