ASP.NET 核心 Openiddict 抛出 "An OpenID Connect response cannot be returned from this endpoint"
ASP.NET Core Openiddict throws "An OpenID Connect response cannot be returned from this endpoint"
我按照 openiddict 服务器示例中的说明使用来自 https://github.com/openiddict/openiddict-samples/tree/master/samples/PasswordFlow 的密码流
但没有成功。
它抛出 InvalidOperationException:无法从此端点返回 OpenID Connect 响应 在路由 /connect/token:
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
邮递员参数:
- 内容类型: application/x-www-form-urlencoded
- 参数: username=..&password=...&grantType=password&scope=offline_access+profile+email
我花了一整天时间进行研究,但没有关于无法从此端点异常返回的信息。还有很多人可以运行 openiddict example 除了我。
这里是Startup.cs的一部分:
services.AddEntityFrameworkSqlite()
.AddDbContext<MisapayContext>(options =>
{
options.UseOpenIddict<int>();
});
//....
services.AddOpenIddict<int>()
.AddEntityFrameworkCoreStores<MisapayContext>()
.DisableHttpsRequirement()
.EnableTokenEndpoint("/connect/token")
.EnableLogoutEndpoint("/connect/logout")
.EnableUserinfoEndpoint("/connect/userinfo")
.UseJsonWebTokens()
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.AddEphemeralSigningKey();
services.AddMvc(config =>
{
config.Filters.Add(new ApiExceptionFilter());
}).AddJsonOptions(options =>
{
options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
});
已编辑: 我认为问题是 OpenIdConnectRequest,如果使用则无法绑定:
OpenIddictBuiler.AddMvcBinders()
将抛出无法从 ASP.NET 上下文检索 OpenID Connect 请求。`
否则去掉,AuthorizationController中的OpenIdConnectRequest可以正常获取。而且还能获取用户名、密码grantType等请求信息……奇怪……对吧?
一些其他信息:
- Asp.net 核心 SDK 1.1
- Project.json : https://gist.github.com/trinvh/47f29468887c209716098bc4c76181a7
- Startup.cs: https://gist.github.com/trinvh/75b7a12fbee754d0ea8cf251f2da9fe9
- AuthorizationController.cs: https://gist.github.com/trinvh/089015b2573cae550856631e72b81374
任何帮助将不胜感激!
好的,这是正在发生的事情:
- 您已将 OpenIddict 配置为使用
/connect/token
作为令牌端点地址。
- 你通过Postman发送的令牌请求指向
/connect/token/
,这实际上是一个完全不同的URL (/connect/token
!= /connect/token/
).
- 由于地址与注册端点路径不同,OpenIddict 不处理请求并拒绝将其视为令牌请求。
- 出于某些原因,MVC 接受处理您的
/connect/token/
请求并调用 Exchange
操作,即使路由与请求的 URL.[=38= 不匹配]
- 由于您没有在 MVC 选项中注册 OpenIddict MVC binder,MVC 使用其默认的 binder 来构造
OpenIdConnectRequest
对象,这允许 OpenIdConnectRequest.GrantType
参数从无效的解析grantType
参数(专用的 OpenIddict 活页夹不会发生这种情况)。
- 您的令牌端点操作最终调用
SignIn
到 return 令牌响应。
- 在幕后,OpenIddict 检测到您在正常令牌请求处理之外调用了
SignIn
- 由于路径差异,它没有将该请求视为令牌请求 - 并中止此不安全操作通过抛出 InvalidOperationException
.
我会通知 MVC 人员以确保他们知道这个错误。
编辑: 经过一些研究,看起来这种行为是 "by design" 并且继承自 ASP.NET MVC。我打开 a feature request in the aspnet/Mvc repository 以添加一种使用 "strict comparison" 进行路由匹配的新方法。
我按照 openiddict 服务器示例中的说明使用来自 https://github.com/openiddict/openiddict-samples/tree/master/samples/PasswordFlow 的密码流 但没有成功。
它抛出 InvalidOperationException:无法从此端点返回 OpenID Connect 响应 在路由 /connect/token:
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
邮递员参数:
- 内容类型: application/x-www-form-urlencoded
- 参数: username=..&password=...&grantType=password&scope=offline_access+profile+email
我花了一整天时间进行研究,但没有关于无法从此端点异常返回的信息。还有很多人可以运行 openiddict example 除了我。
这里是Startup.cs的一部分:
services.AddEntityFrameworkSqlite()
.AddDbContext<MisapayContext>(options =>
{
options.UseOpenIddict<int>();
});
//....
services.AddOpenIddict<int>()
.AddEntityFrameworkCoreStores<MisapayContext>()
.DisableHttpsRequirement()
.EnableTokenEndpoint("/connect/token")
.EnableLogoutEndpoint("/connect/logout")
.EnableUserinfoEndpoint("/connect/userinfo")
.UseJsonWebTokens()
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.AddEphemeralSigningKey();
services.AddMvc(config =>
{
config.Filters.Add(new ApiExceptionFilter());
}).AddJsonOptions(options =>
{
options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
});
已编辑: 我认为问题是 OpenIdConnectRequest,如果使用则无法绑定:
OpenIddictBuiler.AddMvcBinders()
将抛出无法从 ASP.NET 上下文检索 OpenID Connect 请求。`
否则去掉,AuthorizationController中的OpenIdConnectRequest可以正常获取。而且还能获取用户名、密码grantType等请求信息……奇怪……对吧?
一些其他信息:
- Asp.net 核心 SDK 1.1
- Project.json : https://gist.github.com/trinvh/47f29468887c209716098bc4c76181a7
- Startup.cs: https://gist.github.com/trinvh/75b7a12fbee754d0ea8cf251f2da9fe9
- AuthorizationController.cs: https://gist.github.com/trinvh/089015b2573cae550856631e72b81374
任何帮助将不胜感激!
好的,这是正在发生的事情:
- 您已将 OpenIddict 配置为使用
/connect/token
作为令牌端点地址。 - 你通过Postman发送的令牌请求指向
/connect/token/
,这实际上是一个完全不同的URL (/connect/token
!=/connect/token/
). - 由于地址与注册端点路径不同,OpenIddict 不处理请求并拒绝将其视为令牌请求。
- 出于某些原因,MVC 接受处理您的
/connect/token/
请求并调用Exchange
操作,即使路由与请求的 URL.[=38= 不匹配] - 由于您没有在 MVC 选项中注册 OpenIddict MVC binder,MVC 使用其默认的 binder 来构造
OpenIdConnectRequest
对象,这允许OpenIdConnectRequest.GrantType
参数从无效的解析grantType
参数(专用的 OpenIddict 活页夹不会发生这种情况)。 - 您的令牌端点操作最终调用
SignIn
到 return 令牌响应。 - 在幕后,OpenIddict 检测到您在正常令牌请求处理之外调用了
SignIn
- 由于路径差异,它没有将该请求视为令牌请求 - 并中止此不安全操作通过抛出InvalidOperationException
.
我会通知 MVC 人员以确保他们知道这个错误。
编辑: 经过一些研究,看起来这种行为是 "by design" 并且继承自 ASP.NET MVC。我打开 a feature request in the aspnet/Mvc repository 以添加一种使用 "strict comparison" 进行路由匹配的新方法。