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.