Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

form_post response_mode #1591

Closed
Renkas opened this issue Oct 3, 2019 · 17 comments
Closed

form_post response_mode #1591

Renkas opened this issue Oct 3, 2019 · 17 comments

Comments

@Renkas
Copy link

Renkas commented Oct 3, 2019

OIDC implementation is missing form_post response_mode currently. This makes developing a desktop application with OIDC kind of impossible currently.
That's because id_token request will be sent back as URL fragment. That in turn can't be read from system browser through HttpListener.

Spec: https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html

@Renkas Renkas changed the title form_post response_method form_post response_mode Oct 3, 2019
@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

This response mode is exotic and to my knowledge used in legacy scenarios.

That's because id_token request will be sent back as URL fragment. That in turn can't be read from system browser through HttpListener.

That's only true for the implicit flow. However, Hydra supports more modern (and appropriate flows) like Authorization Code + PKCE which are recommended for all (or client side) native applications. All HTLM5 capable browsers can handle this flow.

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

No it's not only true for implicit flow. For all flows that respond with id_token the response_mode will be fragment.

And I'm not talking about browser support for fragments. That's ofcource not issue.

Issue is that we are developing a desktop application which for the authentication uses users system browser (like recommended in spec AFAIK) to get the response. But It's not possible to programmatically read URL fragment from browser.

Just to illustrate the problem have a look at the IdentityModel.OidcClient sample: https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/blob/master/ConsoleSystemBrowser/ConsoleSystemBrowser/Program.cs

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

No it's not only true for implicit flow. For all flows that respond with id_token the response_mode will be fragment.

Yes, because that's the hybrid flow which uses the fragment (based on top of implicit flow). You can get the id token with Authorize Code + PKCE though too, which is the most secure way to date in which is recommended for native applications.

https://www.ory.sh/oauth2-for-mobile-app-spa-browser/

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

How is id_token returned there? I don't see the possibility of it being returned as GET parameter as this is insecure (that's why fragment is used).

Also IdentityModel.OidcClient library that we planned to use does not seem to allow Auth Code + PKCE flow without id_token (which would be fine for our usecase). I created an issue on their repository on that: IdentityModel/IdentityModel.OidcClient#160 .

So currently I have no idea how to implement OAuth2 or OIDC in our desktop app with PKCE. If someone has any suggestions on libraries etc then it would be helpful also.

But I think adding form_post response_mode support would be the best scenario as it would make this server work in much wider usecases.

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

The Authorization Code Exchange returns the ID Token (if requested), that's absolutely standard and highly secure and recommended. Here's an example: https://developer.okta.com/docs/guides/implement-auth-code/exchange-code-token/

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

@aeneasr Hydra will not respond with id_token in my testcase when I'm using Auth Code + PKCE. You mean to tell me it should?

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

Yes of course it does, that's extremely well tested and even certified by the OpenID foundation.

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

I think I have mixed up OAuth2 an OIDC flows in my head already.

I was talking about OIDC AuthorizationCode flow. Which looks like that:

Request sent to server from my application:
https://auth.doman/oauth2/auth?response_type=code&nonce=72de9abc267c16ba7dbd334a8791cb51&state=679c287671f1e9583f2f91fa4eef822e&code_challenge=3dGoeRi9Lu8wv7hWbQcKAsHq2hk7iBLVo9yzWYGNssk&code_challenge_method=S256&client_id=hvxnbzpv9W58Kp-T&redirect_uri=http%3A%2F%2F127.0.0.1%3A7890%2F&response_mode=form_post

Response I get to the redirect_uri:
http://127.0.0.1:7890/?code=IoCHLj5lf58SX6ea5i3K4C4aZKLS3M2yQTNdBOv3c_o.93D0SCzJw4D1U4nZT8a_DGIZoQ49k-5HtzvJChD6Xyc&scope=&state=679c287671f1e9583f2f91fa4eef822e

This does not include id_token (and this is correct I assume then?).

Anyway it seems I just can't use IdentityModel.OidcClient then at all with Hydra? Atleast I can't see how it could be used because id_token response always returns as fragment. And when I'm not requesting id_token then OidcClient itself has an error in validation as it always expects one.

Btw. Thenk you for your time. You have been very helpful on clearing things out once again.

PS! I still think form_post method is a needed feature in Hydra. I don't think I'm only one struggling with this.

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

This does not include id_token (and this is currect I assume then?).

Please read how the auth code flow works, as pointed out above, here: https://developer.okta.com/docs/guides/implement-auth-code/exchange-code-token/

You get the ID Token in the response of the exchange. Only because it isn't visible in the URL doesn't mean it's not there...

Keep in mind that you as with all OIDC flows need to explicitly request and authorize the openid scope.

Anyway it seems I just can't use IdentityModel.OidcClient then at all with Hydra?

I don't know as I've never used that library, but any decent OIDC / OAuth2 library supports fetching the ID Token using the regular (and most commonly used) Authorize Code Flow because that is the standard and most secure way of retrieving access, refresh, and ID tokens, period.

PS! I still think form_post method is a needed feature in Hydra. I don't think I'm only one struggling with this.

I disagree because this is only useful in legacy scenarios where browsers/clients did not have the ability to properly route requests without hashtags (IE9?). This has changed years ago and all browsers now support this rudimental HTML5 feature. Adding this feature won't improve the state of things but it will require us to do another round of certification with the OpenID Foundation with very, very, very limited upsides.

What you're trying to achieve (get an ID token for a native client) is absolutely possible and something very standard that is extremely easy to achieve using regular Authorize Code Flow. Maybe it would be a good idea to take another look at the video from our documentation:

https://www.youtube.com/watch?v=996OiexHze0

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

There are two separate issues that I try to explain clearly - just to be sure we both understand things correctly.

First issue
Yes this library (IdentityModel.OidcClient) supports fetching id_token. But the problem is that because it's part of URL fragment it's impossible for me to access it from my application code. That's because browser API is not providing this information (some security policy in modern browsers). Only workaround for this AFAIK is to use form_post method (which is also default method in this library).
And just to be clear - yes this all works fine inside browser. My problem is with C# desktop application

Second issue
When I try to use OIDC code flow then there is no id_token in the response (as it was not requested). I believe this is correct but you said that there is ALWAYS id_token present. I have checked it now many times. It's not in GET parameters and it's not in BODY.
And real issue with this seems to be with this IdentityModel.OidcClient library not Hydra as this library provides a way to use code flow but errors out because it can't find id_token. I have opened issue on their github on that.

I could not find a way to get id_token as GET parameter in OIDC flow. it always comes back as URL fragment (as it should).


And now I'm in total standstill because I can't find a way to use OIDC in desktop application because I can't access URL fragment and Hydra also does not support form_post response.

Now my only hope I think is to stop using OIDC alltogether and try to find OAuth2 library that knows how to use PKCE flow to use in my desktop application. Haven't had any luck with that right now (maybe havent tried hard enough). Seems like I need to implement the whole client side myself - which does not seem like a good idea.

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

When I try to use OIDC code flow then there is no id_token in the response (as it was not requested). I believe this is correct but you said that there is ALWAYS id_token present. I have checked it now many times. It's not in GET parameters and it's not in BODY.

I said:

Keep in mind that you as with all OIDC flows need to explicitly request and authorize the openid scope.

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

Regarding C#, I have no idea as I do not write Windows Desktop Applications, but I'm sure you're not the first one with this issue. From Google Search results: https://www.scottbrady91.com/OpenID-Connect/ASPNET-Core-using-Proof-Key-for-Code-Exchange-PKCE

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

On top of that, by quickly checking the code on GitHub, IdentityModel supports the authorization code flow: https://github.com/IdentityModel/IdentityModel.OidcClient/blob/635a2051e304b744e3a31eb33c40ccca3728caf2/clients/ConformanceTests/Helper.cs

@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

When I try to use OIDC code flow then there is no id_token in the response (as it was not requested). I believe this is correct but you said that there is ALWAYS id_token present. I have checked it now many times. It's not in GET parameters and it's not in BODY.

I said:

Keep in mind that you as with all OIDC flows need to explicitly request and authorize the openid scope.

So you mean this request should respond with id_token?
https://auth-server/oauth2/auth?response_type=code&nonce=905dc467ee6d774d68cc0f69aed022e4&state=badb871dbc3790e6ab9d2593f8b96498&code_challenge=Zu1g6mA8tb7rAOPUcYrExqMHd3dNrfbS4efZwKrNnHA&code_challenge_method=S256&client_id=hvxnbzpv9W58Kp-T&scope=openid&redirect_uri=http%3A%2F%2F127.0.0.1%3A7890%2F&response_mode=form_post

I dont see it in query or not even in body of response.
http://127.0.0.1:7890/?code=FzW7f9EeyxHOd3IB2Tzif8R9TPCo1-hTrDAgxS1U-Xg.oFyHgCbTuJYT6aNn8soo6KqMTwUI1CmDxyz0Ss8CXEk&scope=&state=badb871dbc3790e6ab9d2593f8b96498


Regarding C#, I have no idea as I do not write Windows Desktop Applications, but I'm sure you're not the first one with this issue. From Google Search results: https://www.scottbrady91.com/OpenID-Connect/ASPNET-Core-using-Proof-Key-for-Code-Exchange-PKCE

Yes exactly. And as you can read from there they are also using form_post response_mode. That's exactly why I also need this response_mode. This flow does not work without it on desktop app AFAIK.


On top of that, by quickly checking the code on GitHub, IdentityModel supports the authorization code flow: https://github.com/IdentityModel/IdentityModel.OidcClient/blob/635a2051e304b744e3a31eb33c40ccca3728caf2/clients/ConformanceTests/Helper.cs

Yes I know. I have tried to use it (example request in this post is also made with this flow) and it's not working because IdentityModel needs id_token in the response but it's not in the response.
I have started an issue on their github on that: IdentityModel/IdentityModel.OidcClient#160

@aeneasr
Copy link
Member

aeneasr commented Oct 3, 2019

I'm sorry but we have to cut this discussion short after my reply, as we're going in circles and I believe that I've answered the questions sufficiently. From my point of view, your use case can be solved with the tools Hydra provides and the current wall being hit is more related to missing puzzle pieces with regards to how OpenID Connect works and/or how Hydra's APIs work.

Keep in mind that you as with all OIDC flows need to explicitly request and authorize the openid scope.

When you exchange the code you will get an ID Token back, but only if you make sure that:

a) the scope openid is requested (this is the case in your example)
b) your consent app tells hydra that openid is in the list of granted scopes

Yes I know. I have tried to use it (example request in this post is also made with this flow) and it's not working because IdentityModel needs id_token in the response but it's not in the response.
I have started an issue on their github on that: IdentityModel/IdentityModel.OidcClient#160

This is, again, most likely related to what I've said already:

Keep in mind that you as with all OIDC flows need to explicitly request and authorize the openid scope.

I will be closing this issue because I have not found sufficient evidence that the response mode form_post will add any additional benefits nor will it make this use case easier, as you would not get an id_token in the response with form_post if you do not request or authorize the openid scope.

Please, read over the documentation again. I believe that everything is laid out in much detail and that there are sufficient materials on how all of this works.

If you find concrete proof or evidence to the contrary of my findings please feel free to comment or request to reopen this issue. But again, all of this works, and to the best of my knowledge with the tools you're using, with more secure flows, without the need form our side to implement something that's really legacy and that will add no additional benefit.

@aeneasr aeneasr closed this as completed Oct 3, 2019
@Renkas
Copy link
Author

Renkas commented Oct 3, 2019

b) your consent app tells hydra that openid is in the list of granted scopes

Thank you. This was the part I was missing somehow in current test case.

Thanks for all the time you wasted on me. It was really helpful.

@mitar
Copy link
Contributor

mitar commented Oct 22, 2020

See #1621 for followup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants