3

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 -

  1. The access_token is obtained with the scope set to read_inbox,write_access,private_info,no_expiry. There are no errors during the authentication. Once the access_token is obtained, am I supposed to use it in every request as per the documentation, or, should I just use the key in the requests?
  2. Including no_expiry in the scope - will this make a difference in the way access_token is used in the URL(s) for the API access?
1
  • George's answer is probably correct, making an http request with an 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. Commented Sep 19, 2012 at 18:01

1 Answer 1

5

First of all, I'm guessing the HTTP 400 errors are directly related to the fact that you are transmitting the access_token over standard HTTP instead of HTTPS. The API (if I remember correctly) throws an error if you try to pass an access token over standard HTTP and immediately invalidates the token.

You actually don't need to include an access_token to make use of most of the API routes. However, if you are making a lot of requests on behalf of other users, using an access token will help out with the number of requests you can make on a daily basis. From the docs:

"If an application does have an access_token, then the application is on a distinct user/app pair daily quota (default size of 10,000)."

So if you really need the extra requests, switching over to HTTPS should solve your problem. If not, then you can simply omit the access_token.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .