c# - C# OWIN OAuth2 服务器:访问令牌总是返回 invalid_grant
问题描述
我正在根据此示例构建 OAuth2 授权服务器:https ://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
我有一个授权码,并试图用它换取一个访问令牌。无论如何,我都会收到 400 响应“invalid_grant”。
这是我的相关服务器实现:
OAuthAuthorizationServerOptions serverOptions = new OAuthAuthorizationServerOptions()
{
AuthorizeEndpointPath = new PathString(authorizePath),
TokenEndpointPath = new PathString(tokenPath),
ApplicationCanDisplayErrors = true,
AllowInsecureHttp = true, // tsk tsk
Provider = new OAuthAuthorizationServerProvider
{
//OnValidateAuthorizeRequest = ValidateAuth,
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
OnGrantClientCredentials = GrantClientCredetails
},
// Authorization code provider which creates and receives authorization code
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode
},
// Refresh token provider which creates and receives referesh token
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
}
};
app.UseOAuthAuthorizationServer(serverOptions);
private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
context.Validated(context.RedirectUri);
return Task.FromResult(0);
}
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
context.Validated();
}
return Task.FromResult(0);
}
private readonly ConcurrentDictionary<string, string> _authenticationCodes =
new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
{
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
_authenticationCodes[context.Token] = context.SerializeTicket();
}
private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
{
string value;
if (_authenticationCodes.TryRemove(context.Token, out value))
{
context.DeserializeTicket(value);
}
context.DeserializeTicket(value);
}
private void CreateRefreshToken(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
}
private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
这是我在客户端请求令牌的地方:
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath + "/";
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret),
};
HttpClient _httpClient = new HttpClient();
var tokenResponse =
await _httpClient.PostAsync(Constants.GARBAGE_TOKEN, new FormUrlEncodedContent(body));
var text = await tokenResponse.Content.ReadAsStringAsync();
到目前为止我测试过的内容:
- 我在所有这些提供程序函数中添加了断点并添加了 context.Validated 任何我可以的地方。以前,它没有命中 ReceiveAuthenticationCode,因为没有在 ValidateClientAuthentication 中验证上下文。这让我假设我在某处错过了验证步骤,但我在其他任何地方都找不到。
- 现在它确实到达了 ReceiveAuthenticationCode、获取令牌并反序列化票证。Context.Identity.Ticket 不为空并且有数据,所以我认为它无论如何都是正确的。
但在那之后 - 我失去了它的踪迹。它以“invalid_grant”的形式返回给调用客户端,我正在努力弄清楚令牌接下来在管道中的哪个位置。据推测,某些提供程序元素正在被调用,由于某种原因将令牌设置为无效,但我一直在倾注 OAuthAuthorizationServerProvider 源,但我什么也没有,似乎没有任何方法可以通过它。事实上,即使知道处理发送令牌的实际响应的代码部分也是有用的;这对我来说都是不透明的。
为什么令牌会失效?它实际上是无效的还是其他一些错误导致它返回 invalid_grant?我如何关注这部分?
我还查看了有关创建一开始链接的 OAuth2 服务器的 microsoft doc 示例,其中大部分都是基于该示例。然而它并没有帮助,因为它使用了这个封装了所有东西的辅助方法:
var authorizationState = _webServerClient.ProcessUserAuthorization(Request);
所以这并不能告诉我太多,而且我也不确定上述助手的工作原理,因为它似乎可以同时处理身份验证代码提交和令牌请求。
解决方案
POST
在请求访问令牌时尝试使用请求。
推荐阅读
- javascript - componentDidMount 中未定义 Ref 属性“焦点”
- c# - Unit testing Custom MessageHandler
- javascript - Electron:将选项卡拖到另一个打开的窗口中
- php - php 显示 "; ?> 不管我做什么
- login - 加载网页不完整 Phantomjs
- quickfix - quickfixj 启动器由于低 seqnum 太低而断开连接
- mapbox - 获取选中的tileset tile的坐标(通过表达式)
- php - 如何在 PHP 中循环网格
- python - 查找数组中特定重复数字的索引
- javascript - 在页面上找到重复的 div ID 名称并使用 Javascript 或 jQuery 附加一个数字