ADFS 4.0:收到无效的客户端凭据
ADFS 4.0: Received invalid Client credentials
知道为什么会发生这种情况吗?
我们的 IT 将 ADFS 从版本 3 更新到版本 4。
更新后,我们的 ASP.NET 核心应用程序出现以下错误:
错误代码:
"Unhandled remote failure. (OAuth token endpoint failure: Status: BadRequest;
Body: {\"error\":\"invalid_client\",\"error_description\":\"MSIS9623: Received invalid Client credentials. The OAuth client is not configured to authenticate using passed in client credentials.\"};)"
要求:
https://.../adfs/oauth2/authorize?client_id=d...4c&scope=&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A44377%2F&state=CfDJ8...Og&resource=https%3A%2F%2Flocalhost%3A44377&redirect_url=https%3A%2F%2Flocalhost%3A44377
我试过也试过:
- "grant_type"="authorization_code"
有人知道 "client credentials" 在这种情况下是什么意思吗?
当您通过向导在 ADFS 端配置应用程序时,您将获得一个 clientId。
这是您在请求中传递的 clientId。
检查您传递的 clientId 是否正确。
另请查看 ADFS 错误日志。
如果发送 "client_secret",ADFS 4.0 会抛出错误。 ADFS 3.0 忽略了该值。
UseOAuthAuthentication 始终发送 "client_secret"。我的 dirty 解决方案是拦截 http 请求并删除 "client_secret"。如果有人有更好的解决方案...
if (securityService.IsOAuthEnabled)
{
HttpClientHandler clientHandler = new HttpClientHandlerInterceptor(){};
var options = securityService.GetOAuthOptions();
options.BackchannelHttpHandler = clientHandler;
app.UseOAuthAuthentication(options);
}
HttpClientHandlerInterceptor:
public class HttpClientHandlerInterceptor : HttpClientHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content is FormUrlEncodedContent)
{
var x = ((FormUrlEncodedContent) request.Content).ReadAsStringAsync().Result;
var contenttype = request.Content.Headers.ContentType.MediaType;
x = x.Replace("client_secret=will+be+ignored&", "");
request.Content = new StringContent(x, Encoding.UTF8, contenttype);
}
return base.SendAsync(request, cancellationToken);
}
}
在您的请求字符串中注意:response_type=code
当我从 ConfigureAuth 函数中注释掉 Startup.Auth.cs 中的 UseOAuthe2CodeRedeemer 时,它缓解了手头的问题.
见下文:
// code_grant is present in the querystring (&code=<code>).
//app.UseOAuth2CodeRedeemer(
// new OAuth2CodeRedeemerOptions
// {
// ClientId = AuthenticationConfig.ClientId,
// ClientSecret = AuthenticationConfig.ClientSecret,
// RedirectUri = AuthenticationConfig.RedirectUri
// }
//);
知道为什么会发生这种情况吗? 我们的 IT 将 ADFS 从版本 3 更新到版本 4。 更新后,我们的 ASP.NET 核心应用程序出现以下错误:
错误代码:
"Unhandled remote failure. (OAuth token endpoint failure: Status: BadRequest;
Body: {\"error\":\"invalid_client\",\"error_description\":\"MSIS9623: Received invalid Client credentials. The OAuth client is not configured to authenticate using passed in client credentials.\"};)"
要求:
https://.../adfs/oauth2/authorize?client_id=d...4c&scope=&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A44377%2F&state=CfDJ8...Og&resource=https%3A%2F%2Flocalhost%3A44377&redirect_url=https%3A%2F%2Flocalhost%3A44377
我试过也试过:
- "grant_type"="authorization_code"
有人知道 "client credentials" 在这种情况下是什么意思吗?
当您通过向导在 ADFS 端配置应用程序时,您将获得一个 clientId。
这是您在请求中传递的 clientId。
检查您传递的 clientId 是否正确。
另请查看 ADFS 错误日志。
如果发送 "client_secret",ADFS 4.0 会抛出错误。 ADFS 3.0 忽略了该值。
UseOAuthAuthentication 始终发送 "client_secret"。我的 dirty 解决方案是拦截 http 请求并删除 "client_secret"。如果有人有更好的解决方案...
if (securityService.IsOAuthEnabled)
{
HttpClientHandler clientHandler = new HttpClientHandlerInterceptor(){};
var options = securityService.GetOAuthOptions();
options.BackchannelHttpHandler = clientHandler;
app.UseOAuthAuthentication(options);
}
HttpClientHandlerInterceptor:
public class HttpClientHandlerInterceptor : HttpClientHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content is FormUrlEncodedContent)
{
var x = ((FormUrlEncodedContent) request.Content).ReadAsStringAsync().Result;
var contenttype = request.Content.Headers.ContentType.MediaType;
x = x.Replace("client_secret=will+be+ignored&", "");
request.Content = new StringContent(x, Encoding.UTF8, contenttype);
}
return base.SendAsync(request, cancellationToken);
}
}
在您的请求字符串中注意:response_type=code
当我从 ConfigureAuth 函数中注释掉 Startup.Auth.cs 中的 UseOAuthe2CodeRedeemer 时,它缓解了手头的问题.
见下文:
// code_grant is present in the querystring (&code=<code>).
//app.UseOAuth2CodeRedeemer(
// new OAuth2CodeRedeemerOptions
// {
// ClientId = AuthenticationConfig.ClientId,
// ClientSecret = AuthenticationConfig.ClientSecret,
// RedirectUri = AuthenticationConfig.RedirectUri
// }
//);