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

OAuth2 Authorization Endpoint Doesn't Use CORS #1211

Closed
bodewig opened this issue Dec 7, 2018 · 9 comments
Closed

OAuth2 Authorization Endpoint Doesn't Use CORS #1211

bodewig opened this issue Dec 7, 2018 · 9 comments

Comments

@bodewig
Copy link

bodewig commented Dec 7, 2018

Describe the bug

Even though CORS is enabled and the request includes an Origin header, the response of the authorization endpoint that redirect to the login endpoint does not contain any Access-Control-Allow-Origin header.

To Reproduce
Steps to reproduce the behavior:

  1. Use this github repository
  2. apply
diff --git a/docker-compose.yml b/docker-compose.yml
index fa50e67a..cf70557f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -64,6 +64,10 @@ services:
       - OAUTH2_SHARE_ERROR_DEBUG=1
       - OIDC_SUBJECT_TYPES_SUPPORTED=public,pairwise
       - OIDC_SUBJECT_TYPE_PAIRWISE_SALT=youReallyNeedToChangeThis
+      - CORS_ENABLED=true
+      - CORS_ALLOWED_ORIGINS=*
+      - CORS_DEBUG=true
+      - LOG_LEVEL=debug
 #     - OAUTH2_ACCESS_TOKEN_STRATEGY=jwt
 #     Uncomment the following lines when configuring tracing
 #      - TRACING_PROVIDER=jaeger
  1. run docker-compose -p hydra up --build
  2. run docker exec -it `docker ps -f name=hydra_hydra_1 -q` hydra clients create --endpoint http://hydra:4445 --id auth-code-client --secret secret --grant-types authorization_code,refresh_token --response-types code,id_token --scope openid,offline --callbacks http://127.0.0.1:5555/callback
  3. run curl -v -H 'Origin: http://localhost' http://localhost:4444/.well-known/openid-configuration - you can see Hydra sets Access-Control-Allow-Origin: * in the response
  4. run curl -v -H 'Origin: http://localhost' http://localhost:4444/oauth2/auth?audience=&client_id=auth-code-client&max_age=0&nonce=ropdgutegfzaxlxddxqfwgts&prompt=&redirect_uri=http%3A%2F%2F127.0.0.1%3A5555%2Fcallback&response_type=code&scope=openid+offline&state=ardsvbolwgdwsqgvfrmavepw

the response is something like

< HTTP/1.1 302 Found
< Location: /oauth2/fallbacks/error?error=invalid_client&error_debug=&error_description=Client+authentication+failed+%28e.g.%2C+unknown+client%2C+no+client+authentication+included%2C+or+unsupported+authentication+method%29&error_hint=The+requested+OAuth+2.0+Client+does+not+exist.
< Date: Fri, 07 Dec 2018 19:08:02 GMT
< Content-Length: 0

Expected behavior
The reponse in the last step contains a Access-Control-Allow-Origin header

Version:

  • Environment: Kubernetes as well as Docker
  • Version v1.0.0rc3

Additional context
https://community.ory.sh/t/authorization-endpoint-bypasses-cors-middleware/812

Adding allowed_cors_origins to the created client doesn't seem to have any effect.

https://github.com/ory/hydra/blob/master/oauth2/handler.go#L173 does not use the corsMiddleware at all which I suspect to be the root cause.

@aeneasr
Copy link
Member

aeneasr commented Dec 8, 2018

There seem to be several things mixed here:

  1. The /oauth2/auth endpoint does not have CORS, it's an endpoint viewed by the browser/user-agent and not by a programmatic client (e.g. browser JS)
  2. The /oauth2/fallbacks/error endpoints do not serve CORS, they are exemplary/default/fallback endpoints that show certain messages when the developer has not configured them.
  3. The client auth-code-client seems to not be properly registered as the error message shows error_hint=The+requested+OAuth+2.0+Client+does+not+exist.. This usually happens when you're running multiple instances of hydra locally (e.g. one in docker, one locally, multiple in docker, ...).

While your original post showed that you set allowed_cors_origins, that's not the case in the above reproduction steps.

@aeneasr
Copy link
Member

aeneasr commented Dec 8, 2018

For clarification, only endpoint /oauth2/token and /oauth2/revoke and wellknown can be consumed as an API, which makes it possible for them to be CORS-able.

@bodewig
Copy link
Author

bodewig commented Dec 8, 2018

Please let me try to explain what I want to do, it is not really an API usage of /oauth2/auth but still requires CORS to be enabled.

I've got two relying parties using the authorization code grant flow with different OAuth2 clients. The consent endpoint is set up to automatically accept the scopes requested and will not show any page.

When the user visits relying party 1 the generated HTML tries to include a snippet of HTML from relying party 2 ("transclusion" implemented in a way similar to https://github.com/gustafnk/h-include). Under the covers this uses the fetch API.

If the user is not yet known to relying party 2 the fetch request results in a redirect to Hydra. As relying party 1 is considered an allowed origin by relying party 2 the redirect is followed and now hits Hydra's authorization endpoint.

In a normal browser flow (the user clicking on a link to relying party 2 rather than using fetch) Hydra would redirect to the login endpoint (with skip=true as the user is remembered) which redirects back to Hydra then to the consent endpoint then to Hydra then to relying party2's redirect URI and finally the page the user wanted to visit in the first place. A lot of redirects but no interaction with the user.

With fetch this stops at the authorization endpoint because the redirect to the login endpoint (which happens) lacks the allowed-origin header. To me this looks like a valid use case for the authorization code grant flow and I want to ask you to reconsider adding CORS support.

I'm sorry if I messed up my "how to reproduce" setup, I've tried to strip it down to the bare minimum needed and overlooked details while doing so. I could fix things - in my real system things work for the "normal" flow so the clients are registered properly and I have added allowed_cors_origins=* without any difference - but this is probably moot if having /oauth2/authsupport CORS is out of question anyway.

@aeneasr
Copy link
Member

aeneasr commented Dec 8, 2018

I think what you're looking for is OIDC Silent Refresh (or similar) which is typically done using a (hidden) iframe (example). The /oauth2/auth endpoint is not to be touched by non-user clients.

@bodewig
Copy link
Author

bodewig commented Dec 8, 2018

Thank you.

I am aware of the OpenID Connect Session spec but it looked like overkill and I think it wouldn't work with our use case as we need to tell a different RP about the user being logged in We could include an iframe from the second party and have it run its authorization code grant flow there but wanted to avoid that. What I was after is more akin to the prompt=none case (which we'd use inside the iframe as well).

After all it is a user client making the request to the authorization endpoint - it is the same browser window just using fetch rather than following a link.

Anyway I can certainly accept if you don't want to change the current state. In that case you may want to close this issue as "wontfix" or whatever seems appropriate ("not a bug", maybe?) and I'll have to think up a workaround for us. Many thanks again for your prompt feedback.

@aeneasr
Copy link
Member

aeneasr commented Dec 8, 2018

No problem, to the best of my knowledge, it is possible to configure fetch in such a way that ignores CORS errors (it will return a response code of 0). With a combination of redirecting to an endpoint that satisfies your CORS requirements for programmatic clients interacting with the OAuth2 Authorization endpoint you might be able to get something done, no guarantees though.

The other, more obvious and easier, solution is to add Nginx with forced CORS for /oauth2/auth in front of Hydra.

Anyway I can certainly accept if you don't want to change the current state. In that case you may want to close this issue as "wontfix" or whatever seems appropriate ("not a bug", maybe?) and I'll have to think up a workaround for us. Many thanks again for your prompt feedback.

Closing as "intentional behaviour". :)

@aeneasr aeneasr closed this as completed Dec 8, 2018
@bodewig
Copy link
Author

bodewig commented Dec 8, 2018

yep, the reverse proxy approach is what I had in mind as well. Thanks.

@aeneasr
Copy link
Member

aeneasr commented Dec 8, 2018

By the way, reason for not adding CORS here is because developers have misconceptions about that endpoint every now and then. Your use case is exotic enough to weigh it as "intentional behaviour" as opposed to fixing a (small) part of the code base, as it will prevent inexperienced devs from accidentally misusing the endpoint (which happens more regularly)!

@bodewig
Copy link
Author

bodewig commented Dec 8, 2018

Understood. Initially I already suspected this was intentional, that's why I asked in the forum first.

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

2 participants