Accessing TradeKing (or any pre-authorized API) with C#/.NET - c#

When setting up an application with TradeKing, you get:
A Consumer Key
A Consumer Secret
A Oauth Token
A Oauth Token Secret
For accessing TradeKing's API, that's apparently all you need to build personal applications. However, I can't find a way to build the correct Oauth headers in C#/.NET.
The examples seem fairly simple, like this Node.js sample. The Oauth library for Node.js takes care of generating the appropriate headers. There are similar samples for a few other languages, but they all seem to have libraries to build the proper header from the provided keys and tokens. I can't find a library to do this with C#/.NET.
I'm trying to wrap my head around what's going on in this SO question that builds the headers from scratch, but it's pretty advanced. I'm poking around in the ASP.NET Security repo, because they must be handling this somewhere. But I can't quite find what I'm looking for.
How can I generate an Oauth header from these keys with .NET?

There is an open source library on CodePlex that has some Oauth management classes set up.
I still need to go through it and take out what isn't necessary, but fortunately it doesn't depend on any other classes from the repo. Once I added it to my project, it was pretty easy to test the connection:
public async Task<IActionResult> MakeRequest()
{
string result;
var oauth = new Oauth.Manager();
// _tradeKing is a configuration object I set up to hold user secrets
oauth["consumer_key"] = _tradeKing.ConsumerKey;
oauth["consumer_secret"] = _tradeKing.ConsumerSecret;
oauth["token"] = _tradeKing.OauthToken;
oauth["token_secret"] = _tradeKing.OauthTokenSecret;
var url = "https://api.tradeking.com/v1/accounts.json";
var authzHeader = oauth.GenerateAuthzHeader(url, "GET");
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Headers["Authorization"] = authzHeader;
var response = await request.GetResponseAsync();
using (var reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return Content(result);
}
There are some more instructions on how to use it from this SO post.

Related

How to send an access_token and id_token to an api using System.Net.Http

how can you send both the access_token and id_token to your api using System.Net.Http? when i was testing my api with postman it seemed to send both tokens and returned the individual user information I needed (a list of products the user is selling). I am unsure how I can do this in my Xamarin app and have being stuck on this for quite some time. I am able to send the access_token as shown below but anything I have tried when sending both tokens has returned a 404 not found. (unauthorized is corrected to a 401 so the access_token is still working)
public async Task<string> GetResponseJsonString(string url)
{
string responseJsonString = null;
var access_token = CrossSecureStorage.Current.GetValue("access_token");
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + access_token);
HttpResponseMessage response = httpClient.GetAsync(url).Result;
responseJsonString = await response.Content.ReadAsStringAsync();
}
return responseJsonString;
}
Note: I am aware the id_token should contain the user information and it should be decoded rather than sending requests for user information. I looked at this and have been unable to find a library that works in a xamarin PCL. I looked at JosePCL.Jwt but was unable to get it to work. I figure since any time I need user information it is returning information from my database that it made sense to send both tokens with the request and let my api get the user information.
This is entirely dependent on the API you're calling. I've never seen an API that needs something more than the access_token it's provided back to you. It's possible you have the nomenclature incorrect here.
Do you mean "access key & secret"? Or are you certain you have an access_token?
In the former case, normally API's will expect things as followed:
Append the key & secret together separated by a ":"
Base64 Encode
Set the Authorization Bearer|Basic header with the result
It's also worth asking if you've tried passing in the id_token as the Authorization header?
It's also also worth asking if you can provide us with a screen capture of the successful response from postman (make sure you obfuscate the sensitive data).
It's also also also worth pointing out an optimization tweak for your code. Since you're using async, it seems you probably are somewhat concerned about performance. Have a look at this article, discussing the disposability of HttpClient. As a better alternative, use HttpRequestMessage as follows:
public async Task<string> GetResponseJsonString(string url)
{
string responseJsonString = null;
var req = new HttpRequestMessage(HttpMethod.Get, "/your/api/url");
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_token);
using (var resp = await client.SendAsync(req))
using (var s = await resp.Content.ReadAsStreamAsync())
using (var sr = new StreamReader(s))
{
if (resp.IsSuccessStatusCode)
{
responseJsonString = await sr.ReadToEndAsync();
}
else
{
string errorMessage = await sr.ReadToEndAsync();
int statusCode = (int)resp.StatusCode;
//log your error
}
}
return responseJsonString;
}
Where client is a reference to a statically shared instance of HttpClient. My preferred way to do all this, is to wrap my API calls, usually one-file-per-service. I inject this service as a singleton, which will broker it's own static instance of HttpClient. This setup is even more straightforward if you're using .NET Core.

Firebase in c# (API recommendation)

I am trying to make a simple program using a firebase database. But i would like to code my client in C# is there any good APIs available? I found a few but some are lacking functions and i would like to know the opinion of someone more experienced in these waters.
There is a REST API which is fairly portable, and you can use this from any .NET language on any supported platform. Dina Cruz has a thorough example of using this API, and you could easily convert this info and use the portable/basic HttpWebRequest type from the BCL instead of whatever Dina used, for example, this is a transliteration of the first POST example from Dina's blog:
var json = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
user = "UserNameValue",
message = "MessageValue"
});
var request = WebRequest.CreateHttp("https://tm-admin-test.firebaseio.com/.json");
request.Method = "POST";
request.ContentType = "application/json";
var buffer = Encoding.UTF8.GetBytes(json);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
var response = request.GetResponse();
json = (new StreamReader(response.GetResponseStream())).ReadToEnd();
// TODO: parse response (contained in `json` variable) as appropriate
There are also several open source projects including Fire#, FirebaseDatabase.net and FirebaseSharp. I'm not sure if these support "all the things."
References
Firebase REST API on google.com
C# example of using Firebase REST API on dinacruz.com
REST examples in C# using WebRequest on StackOverflow.com
Fire# project on github.com
FirebaseDatabase.net project on github.com
FirebaseSharp project on github.com

MVC to WebApi : Can a header be compressed?

I have started to get some issues where I am over the limit with my headers.
I have a MVC controller, calling a WebApi Controller/Service.
I know the trigger, it is a saml-token (xml) that I've converted to base64.
No, I don't have control of the SecurityToken service...so JWT is not an option at this time. Trust me, I've raised my concerns several times.
We use the saml to secure the WebApi Controller(s) using a custom delegating handler that reads the custom-header and transforms it to a ClaimPrincipal...
I have seen gzip code examples for dealing with the Response, but after hours of googling, I haven't found if there is a way to compress my custom header (or all of them if that's the only way)...for the ~Request.
Ideally I would be able to compress the
"X-My-Custom-Header"
and deal with uncompressing it on the webapi side....
So I'm at a loss to know if this is even possible. This is the first time I've ever had to deal with a way too big header issue.
Sample MVC code below. As an FYI, the windows-credentials are sent over, but that contains the Identity that runs the AppPool that runs the MVC.
My custom header is the saml that is associated with the specific logged in User. Thus why I need to send it over and consider it separately from the windows-identity.
using (var client = new HttpClient(HttpClientHandlerFactory.GetWindowsAuthenticationHttpClientHandler()))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string base64SerializedToken = "SuperDuperLongBase64String_IMeanSuperDuper";
client.DefaultRequestHeaders.Add("X-My-Custom-Header", base64SerializedToken);
Uri baseUri = new Uri("http:www.mywebapiservice.com");
Uri destinationUri = new Uri(baseUri, "doSomething");
HttpResponseMessage response = client.PostAsJsonAsync(new Uri(new Uri(this._baseUri), destinationUri.ToString()).ToString(), accountName).Result;
if (response.IsSuccessStatusCode)
{
returnItem = response.Content.ReadAsAsync<MyCustomReturnObject>().Result;
}
else
{
string errorMessage = response.Content.ReadAsStringAsync().Result;
throw new InvalidOperationException(errorMessage);
}
}
public static class HttpClientHandlerFactory
{
public static HttpClientHandler GetWindowsAuthenticationHttpClientHandler()
{
HttpClientHandler returnHandler = new HttpClientHandler()
{
UseDefaultCredentials = true,
PreAuthenticate = true
};
return returnHandler;
}
}
Considering that a SAML token can be several kilobytes in size, depending on the number of claims, sending it as a header is probably a bad idea. Even if you can get it to work now there's no guarantee that it will continue to work if the claim count grows.
Since there is no standard for header compression you will have to modify both ends of the conversation to do something about it. That being the case, why not simply add the SAML token as part of the request body in your API?
If that's really not going to fly (I get that project managers are often painful when it comes to things like this) then you'll have to look into using something like GZipStream to pack the XML, but at some point you're still going to run into problems. This is a bandaid, not a solution.
No, there's no standard for header compression in HTTP. This might have something to do with the fact that you'd need to read the headers to know if (and how) the headers are compressed.
If you don't have a way to decompress whatever manual compression you figure out on the other side, you're out of luck.

How to push to Bitbucket repository with access token?

I used to get the access token from Bitbucket
(with the help of this documentation https://confluence.atlassian.com/display/BITBUCKET/OAuth+on+bitbucket#OAuthonbitbucket-ObtaininganOAuthConsumer)
so I want to pull/push from the logged in user's repository.
How can I use the Bitbucket REST APIs to do that with C# from an ASP.NET MVC application? I would like to implement my logic with the help of this documentation:
https://confluence.atlassian.com/display/BITBUCKET/Use+the+Bitbucket+REST+APIs
I know there is a way to list a user repo with HTTP Authentication like this:
string url = "https://bitbucket.org/api/1.0/user/repositories/";
var request = WebRequest.Create(url) as HttpWebRequest;
string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("username" + ":" + "password"));
request.Headers.Add("Authorization", "Basic " + credentials);
using (var response = request.GetResponse() as HttpWebResponse)
{
var reader = new StreamReader(response.GetResponseStream());
string json = reader.ReadToEnd();
}
But how can I use the token value and secret to push/pull to repository?
Thank you very much!
Looking at the Documentation you sent, https://confluence.atlassian.com/display/BITBUCKET/repositories+Endpoint+-+1.0 - you cannot push/pull to the repository with the API, instead you use the normal way to interact with the git repo - using a commandline tool or whatnot.
You may only alter the meta-data through the API: https://confluence.atlassian.com/display/BITBUCKET/repository+Resource+1.0#repositoryResource1.0-PUTarepositoryupdate
So just use the API client that is commandline: git

How to determine if an HttpResponseMessage was fulfilled from cache using HttpClient

What is the equivalent to WebResponse.IsFromCache when using HttpClient and HttpResponseMessage?
Is there some HTTP header in the response that I can look at?
FYI: The Windows.Web.Http HttpClient (a similar API targetted at Windows 8.1 app development) does include an HttpResponseMessage.Source field that specifies where the result came from (common values are "cache" and "network").
The Windows.Web.Http classes are usable from C# and other .NET languages, from C++, and from JavaScript (when running as a WwaHost app like from the Windows app store).
Can I ask what you're trying to achieve? Are trying to avoid caching?
The reason for asking is I've looked at the source code for HttpClient (specifically HttpClientHandler) and the source for HttpWebResponse and I dont believe you can get this information from the headers.
HttpClient/HttpClientHandler does use HttpWebResponse internally however it does not expose all properties from HttpWebResponse :
private HttpResponseMessage CreateResponseMessage(HttpWebResponse webResponse, HttpRequestMessage request)
{
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(webResponse.StatusCode);
httpResponseMessage.ReasonPhrase = webResponse.StatusDescription;
httpResponseMessage.Version = webResponse.ProtocolVersion;
httpResponseMessage.RequestMessage = request;
httpResponseMessage.Content = (HttpContent) new StreamContent((Stream) new HttpClientHandler.WebExceptionWrapperStream(webResponse.GetResponseStream()));
//this line doesnt exist, would be nice
httpResponseMessage.IsFromCache = webResponse.IsFromCache;// <-- MISSING!
...
}
So your options the way I see it are:
a) Look at the source code for HttpWebRequest to determine the logic for IsFromCache and retrofit this somehow into HttpClient (this may not even be possible, depends on what the logic actually does/needs)
b)ask the ASP.NET team for this property to be included with HttpResponseMessage. either directly as a property or perhaps they could 'keep' the HttpWebResponse
Neither of these options are that great sorry, hence my original question, what are you trying to acheive?
I've been struggling with this scenario recently as well.
What I needed was an integration test to verify that:
Responses for a newly created resource had the correct headers set by the server.
Subsequent requests for that resource were fulfilled from the client-cache.
Responses for an existing resource had the correct headers set by the server as well.
What I ended up doing was a twofold check:
A non-caching HttpClient to check the initial response:
new WebRequestHandler
{
AllowAutoRedirect = true,
UseCookies = true,
CookieContainer = new CookieContainer(),
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Refresh)
};
var client = new HttpClient(handler)
and a second HTTP client to check the client-side cache:
new WebRequestHandler
{
AllowAutoRedirect = true,
UseCookies = true,
CookieContainer = new CookieContainer(),
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default)
};
var client = new HttpClient(handler)
To verify the source of response messages I compare the HttpResponseMessage.Headers.Date values from steps 1 and 2 (which will be the same if the response came from the client cache). For my third step I can just re-use the client from the first step and append an arbitrary string to the URL.
Disclaimer: this applies to .NET Framework 4.7 and ignores best practices concerning HttpClient usage but is seems to do the trick for me in my test suite. An explicit property like the one mentioned above would be preferable but does not seem to be available. Since the last reply here is already a few years old there might be better ways to handle this, but I couldn't think of one.

Categories