Jira API Help C# HttpClient - c#

Okay, so I'm very new to using API's in code and I've been able to use a few that were actually pretty easy. But none of them required authentication. I've been trying to use Jira's REST API service via C#'s HttpClient class. See code below:
public void UpdateJiraIssue(string issueValue)
{
string url = $#"http://jira.mySite.com/rest/api/2/issue/{issueValue}/editmeta";
string jsonString = #"myNeatJsonData";
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
//Initialize Client
HttpClient apiClient = new HttpClient();
apiClient.BaseAddress = new System.Uri(url);
apiClient.DefaultRequestHeaders.Accept.Clear();
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
apiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
async Task RunJiraAPI()
{
using (HttpResponseMessage resp = await apiClient.PostAsync("editmeta", content))
{
if (resp.IsSuccessStatusCode)
{
var jsonSring = await resp.Content.ReadAsStringAsync();
}
}
}
RunJiraAPI();
return;
}
The problem I run into is that I get a 401 error (Authentication). Here's what my 'resp' object contains when I run the code:
resp: {StatusCode: 401, ReasonPhrase: ' ', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
X-AREQUESTID: 400x1314x1
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-ASEN: SEN-11158344
X-AUSERNAME: anonymous
Cache-Control: no-store, no-transform, no-cache
Set-Cookie: atlassian.xsrf.token=B2ZY-C2JQ-1AGH-PBLW_5ccc79da5af8e6abcb9bff5250f3305af3b2877a_lout; Path=/; Secure
WWW-Authenticate: OAuth realm="https%3A%2F%2Fjira.mySite.com"
X-Powered-By: ARR/3.0
X-Powered-By: ASP.NET
Date: Wed, 15 Jan 2020 13:40:22 GMT
Content-Length: 109
Content-Type: application/json; charset=UTF-8
}}
Request Message: {Method: POST, RequestUri: 'https://jira.rhlan.com/rest/api/2/issue/RHD-1116/editmeta', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Authorization: Basic cWE6aGVjc29mdDEyMw==
Accept: application/json
Content-Type: Application/json; charset=utf-8
Content-Length: 70
}}
Status Code: Unauthorized
I need to work on my json string a bit to get it working right (which is why I didn't include what it actually contains), but once I get passed the authentication error, I'll probably actually change things to do a get Jira issue via the API so I can see all the json data returned that way. Then I'll edit my json string accordingly.
Any ideas what I'm doing wrong here?

You can pass in credentials assuming you have a username and an api token.
string credentials= string.Format("{0}:{1}", username, apitoken);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(credentials);
And in your apiClient you can use it like this.
apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteCredentials));

You need a username and api-token. Your api-token should be your login password.

Related

Authorizing AD Group\User With HttpClient

I'm getting a 401 error whenever I attempt to get a response from HttpClient when I turn off Anonymous Authentication.
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers:
{
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcUGFycmlzaFxEb2N1bWVudHNcJ0xSXFNvdXJjZVxBcHBzXExSUiBBRkVcTFJSX0FGLVxhcGlcYWZlXDg0QTk0NjVFQzg2QTQwQjNBNEJCNkJDOTI3MTFGRjNB?=
Cache-Control: private
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Mon, 27 Aug 2018 18:14:05 GMT
Content-Length: 6166
Content-Type: text/html; charset=utf-8
}
For testing I have the controller Authenticating on a single user.
[Authorize(Users = #"Domain\Username")]
public class ExampleController : Controller
{
public async Task<ActionResult> Index(string exampleId)
{
var baseUrl = $"{Request.Url.Scheme}://{Request.Url.Authority}{Url.Content("~")}";
var client = new HttpClient(); // <-- This is WRONG*
var response = await client.GetAsync($"{baseUrl}api/example/{exampleId}");
var example = await response.Content.ReadAsAsync<ExampleModel>();
return View(example);
}
}
I've looked into using HttpClient.DefaultRequestHeaders.Authentication, but I don't see a way to get it to work with ActiveDirectory. I've looked here but can't understand where I'd be getting an authorization token in this case.
If I create a new controller manually and invoke it directly instead of through the API this works, but it really isn't authenticating anything in that case right?
*Edit:
As ADyson points out, my error was not initializing the HttpClient correctly. Here is how it should have been written:
var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
You need to set UseDefaultCredentials = true (in an instance of HttpClientHandler, which you pass to the HttpClient).

Google ML-Engine Predict from C# Authentication issue

Followed
OAuth example
successfully getting bearer token, but response is:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Vary: X-Origin
Vary: Referer
Vary: Origin
Vary: Accept-Encoding
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Alt-Svc: hq=":443"; ma=2592000; quic=51303433; quic=51303432; quic=51303431; quic=51303339; quic=51303335,quic=":443"; ma=2592000; v="43,42,41,39,35"
Transfer-Encoding: chunked
Accept-Ranges: none
Cache-Control: private
Date: Thu, 03 May 2018 13:29:53 GMT
Server: ESF
WWW-Authenticate: Bearer realm="https://accounts.google.com/"
Content-Type: application/json; charset=UTF-8
}}
using a service account with 'ML Engine Developer' Role.
Here is the code:
var url = $"{googleapiprojecturl}/models/{modelname}/versions/{version}:predict";
GoogleCredential credential;
using (Stream stream = new FileStream(#"C:\serviceacctkey.json", FileMode.Open, FileAccess.Read, FileShare.Read))
{
credential = GoogleCredential.FromStream(stream);
}
var bearer_token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync(url);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearer_token);
var content = new StringContent(payloadJsonString, Encoding.UTF8, "application/json");
var responseMessage = await client.PostAsync(url, content);
responseMessage.EnsureSuccessStatusCode();
where googleapiprojecturl = https://ml.googleapis.com/v1/projects/{projectID}
as Chris suggested above, as comment on the question, the answer was scope on the credential before asking for token:
credential = GoogleCredential.FromStream(stream).CreateScoped(new[] { CloudMachineLearningEngineService.Scope.CloudPlatform });
I haven't done this in C#, but I also had trouble in Python with the following similar code:
# Doesn't work
# creds = GoogleCredentials.from_stream(SERVICE_ACCOUNT_FILE)
In Python, the following worked instead:
from oauth2client import service_account
creds = service_account.ServiceAccountCredentials.from_json_keyfile_name('key.json', SCOPES)
creds.get_access_token()
In C#, it looks like you would use the ServiceAccountCredentials class.

How to call Web API (App Service) remotely

I need to call an API from AppService by uri.
This is my API:
public ApiOutputBase Test_AddStudent(string name, int age, string address)
{
return new ApiOutputBase
{
Result = new Result { Status = true, Message = "OK,Test_AddStudent Done!" },
OuputValues = new List<object>() { name, age, address }
};
}
I use this Function to call it:
public async Task<bool> TestCallApi()
{
var client = new HttpClient { BaseAddress = new Uri("http://localhost/") };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var testJson = "{\r\n \"name\": \"MyName\",\r\n \"age\": 25,\r\n \"address\": \"MyAddress\"\r\n}";
HttpResponseMessage response = await client.PostAsync("api/services/myApp/commonLookup/Test_AddStudent", new StringContent(testJson));
// Call api success
if (response.IsSuccessStatusCode)
{
}
return true;
}
I used Swagger to call Test_AddStudent successfully. The testJson was copied from Swagger when I call Test_AddStudent successfully.
After that, I used Swagger to call TestCallApi without any error, but when I tried to debug the value of HttpResponseMessage, it showed this error:
{
StatusCode: 400,
ReasonPhrase: 'Bad Request',
Version: 1.1,
Content: System.Net.Http.StreamContent,
Headers: {
Pragma: no-cache
Cache-Control: no-store, no-cache
Date: Tue, 31 Oct 2017 02:12:45 GMT
Set-Cookie: Abp.Localization.CultureName=en; expires=Thu, 31-Oct-2019 02:12:45 GMT; path=/
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 405
Content-Type: application/json; charset=utf-8
Expires: -1
}
}
Have I missed something?
I finally found the root cause: I passed the wrong input to the api:
Wrong:
var testJson = "{\r\n \"name\": \"MyName\",\r\n \"age\": 25,\r\n \"address\": \"MyAddress\"\r\n}";
HttpResponseMessage response = await client.PostAsync("api/services/myApp/commonLookup/Test_AddStudent", new StringContent(testJson));
Correct:
HttpResponseMessage response = await client.PostAsync("api/services/myApp/commonLookup/Test_AddStudent?name=MyName&age=25&address=MyAdress", "");

Unauthorized access to REST API

I am having a big problem when trying to authenticate to QuickBlox's server using a Token.
The method I use is:
public static async Task<LoginResponse> GetLoginResponseAsync(string email, string password)
{
LoginResponse result = null;
using (var client = new HttpClient())
{
string token = QbProvider.SessionResponse.Session.Token;
LoginRequest request = new LoginRequest()
{
Email = email,
Password = password
};
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, LoginUrlRequest))
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("QB-Token", token);
using (var response = await client.SendAsync(requestMessage))
{
string json = response.Content.ReadAsStringAsync().Result;
result = JsonConvert.DeserializeObject<LoginResponse>(json);
}
}
}
return result;
}
The server's response is:
{"errors":["Token is required"]}
And the headers (debugging) in the client object are:
{
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Date: Thu, 01 Jun 2017 12:05:29 GMT
QuickBlox-REST-API-Version: 0.1.1
Server: openresty/1.9.15.1
Status: 401 Unauthorized
Strict-Transport-Security: max-age=31536000
WWW-Authenticate: OAuth realm=users
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 584a0dca-fc44-4114-9626-327ac1729f67
X-Runtime: 0.003430
X-XSS-Protection: 1; mode=block
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Content-Length: 32
}
}
When I use the Token in Postman, the server's response is successfull.
Do you know what am I doing wrong?
Thank you so much in advance!
Regards.
Try adding your token header using requestMessage.Headers.Add("QB-Token", token) instead of your Authorization one – by #dukedukes

MultipartContent response in Web API

I want to have a possibility to return complex response for requests in Web API. For example I want to return stream with some complex object.
I tried to do it with MultipartFormDataContent:
public static HttpResponseMessage GetMultipartResponse<T>(T responseData, Stream streamToReturn)
{
return new HttpResponseMessage
{
Content = new MultipartContent
{
new StreamContent(streamToReturn),
new ObjectContent<T>(responseData, new JsonMediaTypeFormatter())
}
};
}
I've got a normal HttpResponseMessage on server side. I can see by debugger how my Web API method returns this response, but on the client side I've got an error:
StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNccnVzdGFtX3NhbGFraHV0ZGlub3ZcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xGaWxlU2VydmljZUFQSVxGaWxlU2VydmljZUFQSVxhcGlcZ2V0?=
Cache-Control: no-cache
Date: Tue, 26 Jul 2016 08:30:22 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 1444
Content-Type: application/json; charset=utf-8
Expires: -1
}
There is no other exceptions on client or server side and i can't get some more information with turn on error detail:
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
UPDATE:
Try to read response on client side with:
var result = await response.Content.ReadAsMultipartAsync();
And got this exception:
Invalid 'HttpContent' instance provided. It does not have a content type header starting with 'multipart/'.
Where do I go wrong?
UPDATE 2:
I have normal response on the server side:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.MultipartContent, Headers:
{
Content-Type: multipart/multipart; boundary="3e6d3573-9031-41a7-b7f4-d1421bc1451d"
}
I found the error. I return my multipart content inside using:
using (var stream = MyFileStream())
{
var respone = MultipartResponseHelper.GetMultipartResponse(response, stream, Request);
return respone;
}
So it returns right response, but then stream inside multipartContent will disposed which is the reason of problem.

Categories

Resources