I follow instruction in openiddict server example using password flow from https://github.com/openiddict/openiddict-samples/tree/master/samples/PasswordFlow but have no success.
It throws InvalidOperationException: An OpenID Connect response cannot be returned from this endpoint at route /connect/token:
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
Postman params:
- Content-Type: application/x-www-form-urlencoded
- Params: username=..&password=...&grantType=password&scope=offline_access+profile+email
I spent my day for researching but there is no information about cannot be returned from this endpoint exception. And many people can run openiddict example except me.
Here is apart of 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;
});
Edited: I think problem is OpenIdConnectRequest, it can not be binded if use:
OpenIddictBuiler.AddMvcBinders()
Will throws The OpenID Connect request cannot be retrieved from the ASP.NET context.`
Otherwise, remove it, OpenIdConnectRequest in AuthorizationController can get properly. And I can get request information such as username, password grantType etc... Strange... right?
Some other information:
- Asp.net Core 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
Any help will be appreciated!
Okay, here's what's happening:
- You've configured OpenIddict to use
/connect/token
as the token endpoint address. - The token request you send via Postman points to
/connect/token/
, which is actually a totally different URL (/connect/token
!=/connect/token/
). - Since the address differs from the registered endpoint path, OpenIddict doesn't handle the request and refuses to consider it as a token request.
- For some reasons, MVC accepts to handle your
/connect/token/
request and invokes theExchange
action, even though the route doesn't match the requested URL. - Since you haven't registered the OpenIddict MVC binder in the MVC options, MVC uses its default binder to construct the
OpenIdConnectRequest
object, which allows theOpenIdConnectRequest.GrantType
parameter to be resolved from the invalidgrantType
parameter (it wouldn't happen with the dedicated OpenIddict binder). - Your token endpoint action ends up calling
SignIn
to return a token response. - Under the hood, OpenIddict detects that you called
SignIn
outside the normal token request processing - since it didn't consider the request as a token request, due to the paths difference - and aborts this unsafe operation by throwing anInvalidOperationException
.
I'll ping the MVC folks to make sure they are aware of this bug.
Edit: after some research, it looks like this behavior is "by design" and was inherited from ASP.NET MVC. I opened a feature request in the aspnet/Mvc repository to add a new way to use "strict comparison" for routes matching.
来源:https://stackoverflow.com/questions/42048770/asp-net-core-openiddict-throws-an-openid-connect-response-cannot-be-returned-fr