VersionOne:query.v1 C#OAuth2获得401 Unauthorized错误但rest-1.oauth.v1 / Data /确实有效

时间:2013-09-07 15:05:15

标签: c# api oauth-2.0 versionone

我可以使用OAuth2进行查询,并且:

/rest-1.oauth.v1/Data/Story?sel=Name,Number&Accept=text/json

但是无法 OAuth2 和新的 query1.v1 对Sumnmer2013 VersionOne起作用。我使用两个不同的网址( 401)未经授权指定的方法不受支持

以下是包含工作/rest-1.oauth.v1和非工作query1.v1以及非工作query.legacy.v1的代码。滚动到代码底部以查看Program Main(代码的起始点) 请告知我在这里缺少的东西。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;  
using System.Text;
using System.Threading.Tasks;
using OAuth2Client;

namespace ExampleMemberListCSharp
{
    class Defaults
    {
        public static string Scope = "apiv1";
        //public static string EndpointUrl = "http://localhost/VersionOne.Web";
        public static string EndpointUrl = "https://versionone-test.web.acme.com/summer13_demo";
        public static string ApiQueryWorks = "/rest-1.oauth.v1/Data/Member?Accept=text/json";
        public static string ApiQuery = "/rest-1.oauth.v1/Data/Story?sel=Name,Number&Accept=text/json";
    }


    static class WebClientExtensions
    {
        public static string DownloadStringOAuth2(this WebClient client, IStorage storage, string scope, string path)
        {
            var creds = storage.GetCredentials();
            client.AddBearer(creds);
            try
            {
                return client.DownloadString(path);
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    if (((HttpWebResponse)ex.Response).StatusCode != HttpStatusCode.Unauthorized)
                        throw;
                    var secrets = storage.GetSecrets();
                    var authclient = new AuthClient(secrets, scope);
                    var newcreds = authclient.refreshAuthCode(creds);
                    var storedcreds = storage.StoreCredentials(newcreds);
                    client.AddBearer(storedcreds);
                    return client.DownloadString(path);
                }
                throw;
            }
        }
        public static string UploadStringOAuth2(this WebClient client, IStorage storage
            , string scope, string path, string pinMethod, string pinQueryBody)
        {
            var creds = storage.GetCredentials();
            client.AddBearer(creds);
            client.UseDefaultCredentials = true;
            try
            {
                return client.UploadString(path, pinMethod, pinQueryBody);
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    if (((HttpWebResponse)ex.Response).StatusCode != HttpStatusCode.Unauthorized)
                        throw;
                    var secrets = storage.GetSecrets();
                    var authclient = new AuthClient(secrets, scope);
                    var newcreds = authclient.refreshAuthCode(creds);
                    var storedcreds = storage.StoreCredentials(newcreds);
                    client.AddBearer(storedcreds);
                    client.UseDefaultCredentials = true;
                    return client.UploadString(path, pinMethod, pinQueryBody);
                }
                throw;
            }
        }
    }


    class AsyncProgram
    {
        private static async Task<string> DoRequestAsync(string path)
        {
            var httpclient = HttpClientFactory.WithOAuth2("apiv1");

            var response = await httpclient.GetAsync(Defaults.EndpointUrl + Defaults.ApiQuery);
            var body = await response.Content.ReadAsStringAsync();
            return body;
        }

        public static int MainAsync(string[] args)
        {
            var t = DoRequestAsync(Defaults.EndpointUrl + Defaults.ApiQuery);
            Task.WaitAll(t);
            Console.WriteLine(t.Result);
            return 0;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IStorage storage = Storage.JsonFileStorage.Default;
            using (var webclient = new WebClient())
            {
                // this works:
                var body = webclient.DownloadStringOAuth2(storage, "apiv1", Defaults.EndpointUrl + Defaults.ApiQuery);
                Console.WriteLine(body);
            }
            IStorage storage2 = Storage.JsonFileStorage.Default;

            using (var webclient2 = new WebClient())
            {
                // This does NOT work.  It throws an exception of  (401) Unauthorized:
                 var body2 = webclient2.UploadStringOAuth2(storage2, "apiv1", Defaults.EndpointUrl + "/query.v1", "SEARCH", QueryBody);
                // This does NOT work. It throws an exception of The remote server returned an error: (403): Forbidden."
                var body3 = webclient2.UploadStringOAuth2(storage2, "apiv1", Defaults.EndpointUrl + "/query.legacy.v1", "SEARCH", QueryBody);

                // These do NOT work.  Specified method is not supported:
                var body4 = webclient2.UploadStringOAuth2(storage2, "apiv1", Defaults.EndpointUrl + "/oauth.v1/query.legacy.v1", "SEARCH", QueryBody);
                var body5 = webclient2.UploadStringOAuth2(storage2, "apiv1", Defaults.EndpointUrl + "/oauth.v1/query.legacy.v1", "SEARCH", QueryBody);


            }
            Console.ReadLine();
            AsyncProgram.MainAsync(args);
        }

        public const string QueryBody = @"

from: Story
select:
- Name
";
    }
}

1 个答案:

答案 0 :(得分:0)

此时,query.v1端点需要授予query-api-1.0范围。

您必须将其添加到范围列表中(它可以按空格分隔,例如apiv1 query-api-1.0),然后再次访问授权网址以授权权限。

这个有点重要的信息似乎没有出现在community.versionone.com上的文档中,因此看起来更新是有序的。

此外,目前只有rest-1.oauth.v1query.v1个端点响应OAuth2标头。未来版本将看到它适用于所有端点并删除两种类型的身份验证的端点重复

我在过去尝试使用POST以外的HTTP方法来传输查询时遇到了问题。安全软件,IIS设置和代理可能都以意想不到的方式处理此类请求。