Asana API C# 中的 403 响应

Asana API 403 Response in C#

我正在尝试实现与 Asana 一起使用的 Xamarin 应用 API。

我已经成功实施了 Asana 文档中记录的 OAuth here...至少我认为它是成功的。我从具有 HTTP 状态 "OK".

的 HTTPResponse 中的令牌端点获取访问令牌

但是当我转身并尝试使用相同的访问令牌进行 API 调用时,我收到 403 Forbidden 错误。我在我的浏览器中尝试了相同的 API 调用(登录 Asana 后),它工作正常,这让我相信我确实有权访问该资源,我必须在授权请求时遇到问题我的结局。

有问题的 API 调用是 (documented here): https://app.asana.com/api/1.0/workspaces.

我的C#代码如下(相关部分缩写,并假设ACCESS_TOKEN包含我从令牌交换端点获得的访问令牌):

HttpClient client = new HttpClient();
client.BaseAddress = "https://app.asana.com/api/1.0";
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ACCESS_TOKEN);
client.DefaultRequestHeaders.Add("Accept", "application/json");

然后我在以下函数中使用这个 HttpClient(名为 client):

// Returns a list of the Asana workspace names for the logged in user.
private async Task<List<string>> GetWorkspacesAsync()
{
    List<string> namesList = new List<string>();

    // Send the HTTP Request and get a response.
    this.UpdateToken(); // Refreshes the token if needed using the refresh token.
    using (HttpResponseMessage response = await client.GetAsync("/workspaces"))
    {
        // Handle a bad (not ok) response.
        if (response.StatusCode != HttpStatusCode.OK)
        {
            //  !!!THIS KEEPS TRIGGERING WITH response.StatusCode AS 403 Forbidden!!!

            // Set up a stream reader to read the response.
            // This is for TESTING ONLY
            using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync()))
            {
                // Extract the json object from the response.
                string content = reader.ReadToEnd();
                Debug.WriteLine(content);
            }

            throw new HttpRequestException("Bad HTTP Response was returned.");
        }

        // If execution reaches this point, the Http Response returned with code OK.

        // Set up a stream reader to read the response.
        using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync()))
        {
            // Extract the json object from the response.
            string content = reader.ReadToEnd();
            JsonValue responseJson = JsonValue.Parse(content);

            foreach (JsonValue workspaceJson in responseJson["data"])
            {
                string workspaceName = workspaceJson["name"];
                Debug.WriteLine("Workspace Name: " + workspaceName);

                namesList.Add(workspaceName);
            }
        }
    }

    // I have other awaited interactions with app storage in here, hence the need for the function to be async.

    return namesList;
}

终于找到答案了。看来我使用 HttpClient 不正确;一个微妙的东西应该是等​​效的,但不是由于它的实现方式。

答案

我需要将最后一个斜杠放在 HttpClientBaseAddress 属性 的末尾,而不是特定请求的相对地址的开头。 This answered question explains this.

修复我的代码

我需要更改 BaseAddress 的设置:

HttpClient client = new HttpClient();
client.BaseAddress = "https://app.asana.com/api/1.0/"; // FINAL SLASH NEEDED HERE

并从请求的相对地址中删除斜杠:

// DO NOT put slash before relative address "workspaces" here
using (HttpResponseMessage response = await client.GetAsync("workspaces"))

为什么我得到原来的错误

HttpClientBaseAddress 与我在 GetAsync() 中指定的相对 URI 组合时,它丢弃了一些基址,因为最后的斜杠不包括在内。 BaseAddress 与相对 URI 组合的结果地址是有效的 URL,但在 Asana 中不是有效的 page/API 调用。因此,Asana 自动重定向到登录页面,当然,API 调用的其余部分将被禁止从那里进行。

我是怎么发现这个的

在调试过程中,我获取了我的应用在 Asana 授权期间返回的访问令牌。然后,我自己在 Postman 中重新创建了对“/workspaces”API 的请求,请求按预期工作。这证实我的授权工作正常,问题必须与特定请求有关,而不是授权。在调试过程中,我随后查看了 HttpResponseMessage,它有一个名为 RequestMessage 的 属性,其中包括 GetAsync() 发出请求的实际 URL。我观察到来自 Asana 的登录名 URL,而不是我指定的 BaseAddress...这让我想到了这个问题/ 上面链接的答案。

希望这个解释对遇到类似错误的人有所帮助!