I registered an app, obtained a key and I have implemented the implicit OAuth 2.0 flow in a Windows 8 desktop app (as per the documentation available here). After receiving and storing the access token, whenever I try to use it in a Http GET request, I always end up getting a HTTP 400 "Bad Request" error. A sample URL I am trying to send a GET request to is -
http://api.stackexchange.com/2.1/answers?access_token=[redacted]riLYA%29%29&key=[redacted]p0g%28%28&order=desc&sort=creation&site=stackoverflow&page=1&pagesize=30
What baffles me is that if I remove the access_token
and leave the key
in the request URL, the HTTP response is fine (JSON data downloads and parses fine).
I have a utility method that prepares the URL for the GET request -
public string ToQueryString(Dictionary<string, object> queryParameters)
{
string queryString = "?";
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, object> item in queryParameters)
{
sb.AppendFormat("{0}={1}&", Uri.EscapeDataString(item.Key), Uri.EscapeDataString(item.Value.ToString()));
}
queryString += sb.ToString();
if (queryString.EndsWith("&"))
queryString = queryString.TrimEnd(new char[] { '&'});
return queryString;
}
A typical use of the utility method above is -
private async Task<string> GetAllAnswersJson(string sortOrder, string sortParameter, string siteKey, int? pageNo, int? pageSize)
{
Dictionary<string, object> queryParameters = new Dictionary<string, object>();
queryParameters.Add("order", sortOrder);
queryParameters.Add("sort", sortParameter);
queryParameters.Add("site", siteKey);
if (pageNo.HasValue) queryParameters.Add("page", pageNo.Value.ToString());
if (pageSize.HasValue) queryParameters.Add("pagesize", pageSize.Value.ToString());
queryParameters.Add("key", StackExchangeAuthInfo.AccessKey);
queryParameters.Add("access_token", StackExchangeAuthInfo.AccessToken);
string uri = string.Format(base.Url + ToQueryString(queryParameters));
StackExchangeAPIResponse response = await StackExchangeAPIClient.GET(uri);
if (response.HttpRequestSuccessful)
{
return response.HttpContentString;
}
else
{
return null;
}
}
The GET
method used in the code above is implemented as -
public async static Task<StackExchangeAPIResponse> GET(string url)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip;
var client = new HttpClient(clientHandler);
var query = await client.GetAsync(url);
StackExchangeAPIResponse response = new StackExchangeAPIResponse();
response.HttpStatusCode = query.StatusCode;
response.HttpRequestSuccessful = false;
if (query.IsSuccessStatusCode == true)
{
response.HttpRequestSuccessful = true;
response.HttpContentString = await query.Content.ReadAsStringAsync();
}
return response;
}
I understand that there are several excellent open-source C# (even with async/await) libraries out there, however, the effort I am putting in is to learn the API and other programming challenges. My questions in relation to the above problem -
- The
access_token
is obtained with thescope
set toread_inbox,write_access,private_info,no_expiry
. There are no errors during the authentication. Once theaccess_token
is obtained, am I supposed to use it in every request as per the documentation, or, should I just use thekey
in the requests? - Including
no_expiry
in thescope
- will this make a difference in the wayaccess_token
is used in the URL(s) for the API access?
access_token
should error. The response body should have something like{ error_id: 406, error_name: "access_token_compromised", error_message: "Access token sent over non-HTTPS request, it has been invalidated" }
in it.