如何诊断尝试在 c# .NET Core 中获取 OAuth2 不记名令牌的 401 错误?
Posted
技术标签:
【中文标题】如何诊断尝试在 c# .NET Core 中获取 OAuth2 不记名令牌的 401 错误?【英文标题】:How to diagnose a 401 error attempting to get an OAuth2 bearer token in c# .NET Core? 【发布时间】:2020-05-20 18:18:33 【问题描述】:我在c++
的技能有限,最近搬到了C# (asp.net)
和azure Web services
。作为 PoC,我正在尝试将 REST
调用到 PayPal
(我需要在 3 -6 个月内专业使用它)。
我已经使用说明 here 设置了我的个人 PayPal
帐户,并且我使用 curl 获取了不记名令牌,如链接中所述。惊人的。
我现在正尝试从.NET Core C#
执行此操作,而我得到的只是401 error
。我已经检查了请求,就标题而言,它似乎与 curl 相同;我想我添加的base64
编码凭据与详细 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");
并为我的麻烦获取401
代码。
欢迎提出故障排除建议、更好的解决方法以及嘲笑我的愚蠢。
【问题讨论】:
不确定是不是您的问题,但"client_credientials"
中有错字
@PrestonPHX 这不会有帮助,是吗?很好的收获,谢谢。
【参考方案1】:
更新:
我阅读了文档,有几项让我印象深刻:
需要一个后置动词。 使用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();
【讨论】:
这段代码也给出了 401。哪里是开始诊断更广泛问题的好地方?我查看了发回的标头,似乎没有任何帮助。 是的,我有,它工作正常(并为延迟响应表示歉意)。 您确定您的编码格式正确吗? 不,我不是。我正在使用我发布的代码和您建议的 sn-p。您将如何对请求进行编码以及验证其是否正确完成的最佳方式是什么?【参考方案2】:为了未来读者的利益:
正如建议的那样,这是一个编码问题。行:
var clientCreds = System.Text.Encoding.UTF8.GetBytes(clientCredString);
需要
var clientCreds = System.Text.Encoding.ASCII.GetBytes(clientCredString);
还应注意,此特定操作需要 POST 而不是我使用的 GET,但是一旦我开始发送正确编码的请求,错误就开始变得更有意义了。
【讨论】:
以上是关于如何诊断尝试在 c# .NET Core 中获取 OAuth2 不记名令牌的 401 错误?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 页面 ASP.NET Core MVC 上使用 SignInManager 和 Usermanager
如何从 RSA 公钥 XML 文件 .net core c# 中获取 n 值