如何诊断试图在c#NET内核中获取OAuth2承载令牌时发生的401错误?

如何诊断试图在c#NET内核中获取OAuth2承载令牌时发生的401错误?,c#,.net-core,paypal,oauth-2.0,C#,.net Core,Paypal,Oauth 2.0,我在c++方面的技能有限,最近加入了c#(asp.net)和azurewebservices。作为一名PoC,我正在尝试调用REST进入PayPal(我需要在3-6个月内进行专业使用) 我已经使用说明设置了我的个人PayPal帐户,并使用链接中描述的curl获得了一个不记名令牌。太棒了 我现在正试图从.netcore C#执行此操作,我得到的只是一个401错误。我已经检查了请求,它在头方面似乎与curl相同;我想添加的base64编码凭据与verbose curl日志中的凭据相同(我用眼睛检查了

我在
c++
方面的技能有限,最近加入了
c#(asp.net)
azurewebservices
。作为一名PoC,我正在尝试调用
REST
进入
PayPal
(我需要在3-6个月内进行专业使用)

我已经使用说明设置了我的个人
PayPal
帐户,并使用链接中描述的curl获得了一个不记名令牌。太棒了

我现在正试图从
.netcore C#
执行此操作,我得到的只是一个
401错误
。我已经检查了请求,它在头方面似乎与curl相同;我想添加的
base64
编码凭据与verbose curl日志中的凭据相同(我用眼睛检查了两个
base64
字符串),因此它一定是我在设置调用时正在做(或没有做)的事情。我在寻找对我犯下的明显错误的建议、指点或坦率的笑声

我设立了一个我认为是命名客户的机构:

 public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHttpClient("PayPal", c =>
            {
                c.BaseAddress = new Uri("https://api.sandbox.paypal.com/v1/");
                c.DefaultRequestHeaders.Add("Accept", "application/json");
                c.DefaultRequestHeaders.Add("Accept-Language", "en_US");
            });
(为了简洁起见,省略了与VS一起免费提供的所有其他内容)

我尝试这样做:

           string clientCredString = CLIENTID + ":" + SECRET;
            var clientCreds = System.Text.Encoding.UTF8.GetBytes(clientCredString);
            var client = _clientFactory.CreateClient("PayPal");
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(clientCreds));
            var messageBody = new Dictionary<string,string > ();
            messageBody.Add("grant_type", "client_credientials");
            var request = new HttpRequestMessage(HttpMethod.Get, "oauth2/token")
            {
                Content = new FormUrlEncodedContent(messageBody)
            };
            string token;
            var response = await client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                token = JsonConvert.DeserializeObject<string>(json);

            }
            else 
            {
                throw new ApplicationException("Well that failed");
            }
string clientCredString=CLIENTID+:“+SECRET;
var clientCreds=System.Text.Encoding.UTF8.GetBytes(clientCredString);
var client=_clientFactory.CreateClient(“贝宝”);
client.DefaultRequestHeaders.Authorization=new System.Net.Http.Headers.AuthenticationHeaderValue(“Basic”,System.Convert.ToBase64String(clientCreds));
var messageBody=newdictionary();
添加(“授权类型”、“客户凭证”);
var request=newhttprequestmessage(HttpMethod.Get,“oauth2/token”)
{
内容=新的FormUrlEncodedContent(messageBody)
};
字符串标记;
var response=wait client.sendaync(请求);
if(响应。IsSuccessStatusCode)
{
var json=await response.Content.ReadAsStringAsync();
token=JsonConvert.DeserializeObject(json);
}
其他的
{
抛出新的ApplicationException(“失败的井”);
}
为我的麻烦找一个
401
密码

对故障排除的建议,更好的解决方法,以及对我愚蠢的嘲笑都表示欢迎

更新:

我阅读了文档,其中有几个项目非常突出:

  • 需要一个post动词
  • 对客户端凭据使用
    FormUrlEncodedContent
  • 基本身份验证需要用户名和密码(客户端Id和密码)
我认为语法应该是:

var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "...");
request.Content = new Dictionary<string, string>() { "grant_type", "client_credentials" };
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", $"{Encoding.UTF8.GetBytes($"{id}:{secret}")}");
HttpResponseMEssage = response = await client.PostAsync(request);

response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
var-client=new-HttpClient();
使用var request=newhttprequestmessage(HttpMethod.Post,“…”);
request.Content=newdictionary(){“grant\u type”,“client\u credentials”};
request.Headers.Authorization=newauthenticationHeaderValue(“Basic”,$”{Encoding.UTF8.GetBytes($”{id}:{secret}”)});
HttpResponseMEssage=response=Wait client.PostAsync(请求);
response.EnsureSuccessStatusCode();
var content=await response.content.ReadAsStringAsync();

为了未来读者的利益:

正如所暗示的,这是一个编码问题。该行:

var clientCreds = System.Text.Encoding.UTF8.GetBytes(clientCredString);
需要

var clientCreds = System.Text.Encoding.ASCII.GetBytes(clientCredString);

还需要注意的是,这个特定的操作需要一个POST,而不是我使用的GET,但一旦我开始发送正确编码的请求,错误就会变得更有意义。

不确定这是否是您的问题的原因,但在
“客户机”中输入的错误将不会有帮助,是吗?很好,谢谢。这个代码也给出了一个401。哪里是开始诊断更广泛问题的好地方?我查看了发送回来的标题,似乎没有任何帮助。是的,我查看了,它工作正常(并对延迟响应表示歉意)。您确定编码格式正确吗?不,我没有。我正在使用我发布的代码和您建议的代码片段。您将如何对请求进行编码,以及验证请求是否正确的最佳方法是什么?