unauthorized error when using HttpClient - c#

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
namespace ConsoleProgram
{
public class Class1
{
private const string URL = "https://sun.domain.com/v1/service/token";
static void Main(string[] args)
{
var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("admin#client", "admin");
HttpClient client = new HttpClient(handler);
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", "admin", "admin"))));
// client.BaseAddress = new Uri(URL);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
// List data response.
HttpResponseMessage response = client.GetAsync(URL).Result; // Blocking call!
String res = response.ToString();
Console.WriteLine(res);
}
}
}
I am getting unauthorized error even though I am passing the correct credentials. Any ideas?
I tried almost all the answers posted on StackOverflow.

For Basic Authentication, you need to send the credentials in an authorization header called "Basic" with base64-encoded "username:password" as the value. This should get the job done:
var headerVal = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin#client:admin"));
var header = new AuthenticationHeaderValue("Basic", headerVal);
client.DefaultRequestHeaders.Authorization = header;

Related

How can i get Headers value with Net Core?

I send a request on the API, the request and the response are successful, but I want to get the value equivalent to the authentication keyword through the response. How can I do that? I tried this way on the examples I found, but it doesn't give any results .Net 6.0
using LoggerApi.Login;
using System;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
using System.Linq;
using Microsoft.Extensions.Primitives;
namespace LoggerApi.Login
{
public class AdminLogin
{
public async static Task<object> GetAuthenticationCode()
{
var client = new HttpClient();
var loginEndpoint = new Uri("https://admin.com/login");
var loginPayload = new LoginPayload()
{
Username = "admin",
Password= "admin",
};
var requestJson = JsonConvert.SerializeObject(loginPayload);
var payload = new StringContent(requestJson, Encoding.UTF8, "application/json");
var res = await client.PostAsync(loginEndpoint, payload).Result.Headers.TryGetValues("authentication");
return res;
}
}
}

How to properly do this C# MultiPartFormDataContent API Call?

I am currently trying to make an api call in c# using a MultiPartFormDataContent but I keep
getting the following error:
"Response: {"statusCode":400,"error":"Bad Request","message":""Image file" must be of type object","validation":{"source":"payload","keys":["images"]}}"
This is my Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Example
{
public class Test
{
public static void Main(string[] args)
{
Task<string> test = testFunction();
Console.WriteLine("Result: " + test.Result);
}
public static async Task<string> testFunction()
{
const string file = "C:\\ExamplePath\\image_1.jpeg";
const string URL = "https://example-api?api-key=example-key";
string boundary = "---8d0f01e6b3b5dafaaadaad";
MultipartFormDataContent multipartContent = new MultipartFormDataContent(boundary);
var streamContent = new StreamContent(File.Open(file, FileMode.Open));
var stringContent = new StringContent("flower");
multipartContent.Add(stringContent, "organs");
multipartContent.Add(streamContent, "images");
try
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(URL, multipartContent);
Console.WriteLine("Response: " + await response.Content.ReadAsStringAsync());
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine("IN METHIOD: " + content);
return content;
}
return null;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
}
It's obviously a problem with how I am trying to do the api call but I don't know how to do it with an object instead like mentioned the error message.
This link has some good examples and where I actually got my code snippet from below.
Here's a basic example of using MultiFormDataContent:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
I hope this helps or points you in the right direction.

Microsoft AnalysisServices - start and stop server using Azure Functions

I wanted to write an Azure Function to stop and resume MS Analysis Sevice.
I have been tasked to do this using API Resume and API Suspend.
It's my first time with C# (I have Python/Javascript background).
What am I doing wrong? Can someone provide correct solution? Would be grateful from the bottom of my heart.
Here is my current code sample:
using System;
using System.Net;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
static HttpClient client = new HttpClient();
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req)
{
var subscriptionId = "mySId";
var resourceGroupName = "myRGName";
var serverName = "mySName";
var APIurl = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AnalysisServices/servers/{serverName}/resume?api-version=2017-08-01";
var response = await client.PostAsync(APIurl, null);
string result = await response.Content.ReadAsStringAsync();
return req.CreateResponse(HttpStatusCode.OK);
}
This is what I get in console. Server is not stopping though.
As the api "Resume" you mentioned in your question requires Azure Active Directory OAuth2 Flow, so you need to get the access token first by referring to this tutorial and then use the access token to request this api in your function code.
In the code of your function app, you need to set the access token which we get above as the value of Authorization and then do the post reuqest.
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token");
For those in times of need - this is my complete working solution.
using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Net.Http.Headers;
using System.Net;
using System.Net.Http;
using System.Collections.Generic;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
namespace ManageAS
{
public class ManageAS
{
string accessToken = null;
string responseString = null;
string serverStatus = null;
string serverFullURI = Environment.GetEnvironmentVariable("FULL_SERVER_URI");
static string shortServerName = Environment.GetEnvironmentVariable("SHORT_SERVER_NAME");
string resourceURI = "https://management.core.windows.net/";
string clientID = Environment.GetEnvironmentVariable("CLIENT_ID");
string clientSecret = Environment.GetEnvironmentVariable("CLIENT_SECRET");
string tenantID = Environment.GetEnvironmentVariable("TENANT_ID");
static string resourceGroupName = Environment.GetEnvironmentVariable("RESOURCE_GROUP_NAME");
static string subscriptionId = Environment.GetEnvironmentVariable("SUBSCRIPTION_ID");
static Uri apiURI = null;
[FunctionName("PerformAction")]
public async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req,
ILogger log)
{
await GetAccessToken();
await GetServerStatus(accessToken);
if (serverStatus == "Paused")
{
apiURI = new Uri(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AnalysisServices/servers/{2}/resume?api-version=2017-08-01", subscriptionId, resourceGroupName, shortServerName));
this.responseString = await ServerManagement(apiURI, accessToken);
}
if (serverStatus == "Succeeded")
{
apiURI = new Uri(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AnalysisServices/servers/{2}/suspend?api-version=2017-08-01", subscriptionId, resourceGroupName, shortServerName));
this.responseString = await ServerManagement(apiURI, accessToken);
}
return req.CreateResponse(HttpStatusCode.OK, responseString);
}
protected async Task<string> GetAccessToken()
{
string authority = "https://login.microsoftonline.com/" + tenantID;
AuthenticationContext authenticationContext = new AuthenticationContext(authority);
var token = await authenticationContext.AcquireTokenAsync(resourceURI, new ClientCredential(clientID, clientSecret));
accessToken = token.AccessToken;
return accessToken;
}
protected async Task<string> ServerManagement(Uri url, string token)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await client.PostAsync(url.ToString(), null);
response.EnsureSuccessStatusCode();
HttpContent content = response.Content;
string json;
json = await content.ReadAsStringAsync();
return json;
}
protected async Task<string> GetServerStatus(string token)
{
var url = new Uri(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AnalysisServices/servers/{2}?api-version=2017-08-01", subscriptionId, resourceGroupName, shortServerName));
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await client.GetAsync(url.ToString());
response.EnsureSuccessStatusCode();
string sJson = await response.Content.ReadAsStringAsync();
var dictResult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(sJson);
if (!dictResult.ContainsKey("properties")) return null;
var dictProperties = dictResult["properties"] as Newtonsoft.Json.Linq.JObject;
if (dictProperties == null || !dictProperties.ContainsKey("state")) return null;
serverStatus = Convert.ToString(dictProperties["state"]);
return serverStatus;
}
}
}

Error retrieving token ASP.NET Web API template iis 7.5 404 not found

I’m working with a project that has been created as a ASP.Net Web Application with the ‘Web API’ template and ‘Individual User Accounts’ enabled as the authentication option. I have a console application that consumes the web api. But When I want to get the token it gives me a complete html string with "404 not found" in stead of a json array. What am I doing wrong?
This is mij console app code:
using ConsoleApplication1.Helpers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
const string userName = "user#user.com";
const string password = "Password01!";
const string apiBaseUri = "http://localhost/WebAPITest";
const string apiGetPeoplePath = "/api/people";
static void Main(string[] args)
{
//Get the token
var token = GetAPIToken(userName, password, apiBaseUri).Result;
Console.WriteLine("Token: {0}", token);
//Make the call
var response = GetRequest(token, apiBaseUri, apiGetPeoplePath).Result;
Console.WriteLine("response: {0}", response);
//wait for key press to exit
Console.ReadKey();
}
private static async Task<string> GetAPIToken(string userName, string password, string apiBaseUri)
{
using (var client = new HttpClient())
{
//setup client
client.BaseAddress = new Uri(apiBaseUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//setup login data
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", userName),
new KeyValuePair<string, string>("password", password),
});
//send request
HttpResponseMessage responseMessage = await client.PostAsync("/Token", formContent);
//get access token from response body
var responseJson = await responseMessage.Content.ReadAsStringAsync();
var jObject = JObject.Parse(responseJson);
return jObject.GetValue("access_token").ToString();
}
}
static async Task<string> GetRequest(string token, string apiBaseUri, string requestPath)
{
using (var client = new HttpClient())
{
//setup client
client.BaseAddress = new Uri(apiBaseUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
//make request
HttpResponseMessage response = await client.GetAsync(requestPath);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
}
}
This is my Startup.Auth:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}
After a couple of days thinking and trying. I found a solution that worked for me. In my previous code it worked only in iisexpress (I don't know why so if someone knows please share!). But in my new code it worked for both iisexpress and iis 7.5.
using ConsoleApplication1.Helpers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
const string userName = "user#user.com";
const string password = "Password01!";
const string apiBaseUri = "http://localhost/WebAPITest";
private static async void GetAPIToken()
{
string responseJson = await ResponseAsStringAsync(string.Format("{0}/token", apiBaseUri),
new[]
{
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("username", userName),
new KeyValuePair<string, string>("grant_type", "password"),
});
var jObject = JObject.Parse(responseJson);
string token = jObject.GetValue("access_token").ToString();
}
public static async Task<string> ResponseAsStringAsync(string url, IEnumerable<KeyValuePair<string, string>> postData)
{
string responseString = string.Empty;
var uri = new Uri(url);
using (var client = new HttpClient())
using (var content = new FormUrlEncodedContent(postData))
{
content.Headers.Clear();
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
HttpResponseMessage response = await client.PostAsync(uri, content);
responseString = await response.Content.ReadAsStringAsync();
}
return responseString;
}
static void Main(string[] args)
{
GetAPIToken();
Console.ReadKey();
}
}
}
I hope it helps someone else with the same problem.

Trying to Post a Slack Message through NameValueCollection using HttpClient.PostAsync instead of WebClient

I am trying to use HttpClient to post a NameValueCollection to a specific Url. I have the code working using WebClient, but I'm trying to figure out if it is possible to do using HttpClient.
Below, you will find my working code that uses WebClient:
var payloadJson = JsonConvert.SerializeObject(new { channel, username, text });
using (var client = new WebClient())
{
var data = new NameValueCollection();
data["payload"] = payloadJson;
var response = client.UploadValues(_uri, "POST", data);
var responseText = _encoding.GetString(response);
}
I'm using this code to try to post a message to a Slack Channel using a web integration. Is there a way to implement this same functionality while using HttpClient?
The Slack error that I receive when I try to use HttpClient is "missing_text_or_fallback_or_attachment".
Thanks in advance for any help!
Using HttpClient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://yourdomain.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new NameValueCollection();
data["payload"] = payloadJson;
StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync("api/yourcontroller", content);
if (response.IsSuccessStatusCode)
{
//MessageBox.Show("Upload Successful", "Success", MessageBoxButtons.OK);
}
}
catch (Exception)
{
// ignored
}
}
While you are tagging #slack in the question, I suggest you to use Slack.Webhooks nuget package.
Example usage I found is in here;
https://volkanpaksoy.com/archive/2017/04/11/Integrating-c-applications-with-slack/
var url = "{Webhook URL created in Step 2}";
var slackClient = new SlackClient(url);
var slackMessage = new SlackMessage
{
Channel = "#general",
Text = "New message coming in!",
IconEmoji = Emoji.CreditCard,
Username = "any-name-would-do"
};
slackClient.Post(slackMessage);

Categories