我正在使用Visual Studio 2015 Enterprise和ASP.NET vNext Beta8来构建一个端点,该端点同时发布和使用JWT令牌,详见here。正如该文章中所解释的那样,端点使用AspNet.Security.OpenIdConnect.Server(AKA OIDC)来完成繁重的任务。
在我们的内部开发环境中使用此原型时,我们遇到了使用负载均衡器的问题。特别是,我们认为它与app.UseJwtBearerAuthentication上的“权限”设置和我们特殊的http / https组合有关。使用我们的负载平衡环境,任何使用令牌调用REST方法的尝试都会产生以下异常:
WebException:无法解析远程名称:'devapi.contoso.com.well-known' HttpRequestException:发送请求时发生错误 IOException:IDX10804:无法从“https://devapi.contoso.com.well-known/openid-configuration”检索文档。
请考虑以下步骤进行复制(这是为了进行原型设计,不应该被认为是值得的产品):
我们使用OIDC创建了一个beta8原型,如here所述。
我们将项目部署到在Server 2012 R2上运行的2个配置相同的IIS 8.5服务器。 IIS服务器托管一个名为“API”的beta8站点,在所有可用的IP地址上绑定到端口80和443,主机名为“devapi.contoso.com”(在本文中为此目的而清理)。
两台IIS服务器都有一个指向自己的主机条目:
127.0.0.1 devapi.contoso.com
我们的网络管理员已将*证书(* .contoso.com)与我们的Kemp负载均衡器绑定,并将https://devapi.contoso.com的DNS条目配置为解析为负载均衡器。
现在这很重要,负载均衡器也已配置为使用 http 代理https到IIS服务器的流量(不,重复,不是在https上)。我已经向我解释过,这是我们公司的标准操作程序,因为他们只需要在一个地方安装证书。 我们不确定为什么我们的网络管理员在IIS中绑定了443,因为理论上它从未在此端口上接收任何流量。
我们通过https发送一个安全的帖子到https://devapi.contoso.com/authorize/v1来获取令牌,该工作正常(有关如何发布此帖子的详细信息为here):
{
“sub”:“todo”,
“iss”:“https://devapi.contoso.com/”,
“aud”:“https://devapi.contoso.com/”,
“exp”:1446158373,
“nbf”:1446154773
}
然后,我们将此令牌用于另一个安全通过https转到https://devapi.contoso.com/values/v1/5。
OpenIdConnect.OpenIdConnectConfigurationRetriever抛出异常:
WebException:无法解析远程名称:'devapi.contoso.com.well-known' HttpRequestException:发送请求时发生错误 IOException:IDX10804:无法从“https://devapi.contoso.com.well-known/openid-configuration”检索文档。
我们认为这是因为OIDC正在尝试咨询“options.Authority”中指定的主机,我们在启动时将其设置为https://devapi.contoso.com/。此外,我们推测,因为我们的环境已配置为将https流量转换为负载均衡器和IIS之间的非https流量,所以当框架尝试解析https://devapi.contoso.com/时出现问题。我们尝试了许多配置更改,甚至将权限指向非安全http://devapi.contoso.com也无济于事。
非常感谢帮助我们理解这个问题的任何帮助。
答案 0 :(得分:1)
@Pinpoint是对的。此异常是由允许IdentityModel启动非HTTPS调用的OIDC配置代码路径引起的。特别是我们使用的代码示例对权限URI中缺少尾部斜杠敏感。这是一个代码片段,它使用Uri类以可靠的方式组合路径,无论Authority URI是否有尾部斜杠:
public void Configure(IApplicationBuilder app, IOptions<AppSettings> appSettings)
{
.
.
.
// Add a new middleware validating access tokens issued by the OIDC server.
app.UseJwtBearerAuthentication
(
options =>
{
options.AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme ;
options.AutomaticAuthentication = false ;
options.Authority = new Uri(appSettings.Value.AuthAuthority).ToString() ;
options.Audience = new Uri(appSettings.Value.AuthAuthority).ToString() ;
// Allow IdentityModel to use HTTP
options.ConfigurationManager =
new ConfigurationManager<OpenIdConnectConfiguration>
(
metadataAddress : new Uri(new Uri(options.Authority), ".well-known/openid-configuration").ToString(),
configRetriever : new OpenIdConnectConfigurationRetriever() ,
docRetriever : new HttpDocumentRetriever { RequireHttps = false }
);
}
);
.
.
.
}
在这个例子中,我们通过“appSettings.Value.AuthAuthority”从config.json中提取Authority URI,然后使用Uri类清理/组合它。