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

[TT-955] bug: CORS options_passthrough on Non OPTIONS requests #1506

Open
asoorm opened this issue Mar 2, 2018 · 7 comments
Open

[TT-955] bug: CORS options_passthrough on Non OPTIONS requests #1506

asoorm opened this issue Mar 2, 2018 · 7 comments

Comments

@asoorm
Copy link
Member

asoorm commented Mar 2, 2018

When Enable CORS: false and Options Passthrough: true. In the scenario where the gateway is short-circuiting the proxy, for example due to failed auth, the response headers do not contain required CORS headers.

It is expected by Browsers that the SAME CORS headers returned from an OPTIONS request will be returned on a POST request for example.

Steps to Recreate:

Browser sends preflight OPTIONS request to GW, GW transparently reverse proxy preflight request to upstream. CORS headers returned.

$ curl -X OPTIONS https://tyk-gateway.dev:8080/httpbin/post -H 'Origin: abc.com' -k -v
> OPTIONS /httpbin/post HTTP/1.1
> Host: tyk-gateway.dev:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: abc.com
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
< Access-Control-Allow-Origin: abc.com
< Access-Control-Max-Age: 3600
< Allow: POST, OPTIONS
< Connection: close
< Content-Length: 0
< Content-Type: text/html; charset=utf-8
< Date: Fri, 02 Mar 2018 13:15:42 GMT
< Server: meinheld/0.6.1
< Via: 1.1 vegur
< X-Powered-By: Flask
< X-Processed-Time: 0
< X-Ratelimit-Limit: 0
< X-Ratelimit-Remaining: 0
< X-Ratelimit-Reset: 0
<

Browser sends actual request to Gateway. But with invalid credentials - which means 4xx failure.

$  curl -X POST https://tyk-gateway.dev:8080/httpbin/post -H 'Origin: abc.com' -H 'Authorization: Bearer JUNK' -k -v
> POST /httpbin/post HTTP/1.1
> Host: tyk-gateway.dev:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: abc.com
> Authorization: Bearer JUNK
>
< HTTP/1.1 403 Forbidden
< Content-Type: application/json
< Date: Fri, 02 Mar 2018 13:18:32 GMT
< Content-Length: 37
<
{
    "error": "Key not authorized"
}

This is because the gateway has short-circuited the connection and never hits the upstream in order to get the CORS headers.

Possible Workarounds / Thoughts / Considerations:

1. Enable CORS in the gateway as well as options_passthrough.

This will enable, in the event of a non-simple and non-options request for Tyk to return it's own CORS headers.

$ curl -X POST https://tyk-gateway.dev:8080/httpbin/post -H 'Origin: https://abc.com' -H 'Authorization: Bearer JUNK' -k -v
> POST /httpbin/post HTTP/1.1
> Host: tyk-gateway.dev:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: https://abc.com
> Authorization: Bearer JUNK
>
< HTTP/1.1 403 Forbidden
< Access-Control-Allow-Origin: https://abc.com
< Content-Type: application/json
< Vary: Origin
< Date: Fri, 02 Mar 2018 13:23:47 GMT
< Content-Length: 37
<
{
    "error": "Key not authorized"
}

Pro: Simple solution.
Con: Need to configure to return exactly same CORS headers as was provided by the initial OPTIONS request, otherwise browser will complain.

2. Given certain conditions, perform OPTIONS request to upstream and merge CORS headers with error response

Pro: Should be correct every time
Con: Complexity from code perspective, error handling for CORS request, multiple OPTIONS requests to upstream

3. Cache initial OPTIONS request
When an OPTIONS request is performed, it is implied that a follow-up request will be made. For a short period of time, we can cache the headers of the preflight response.

When real request is sent, if short-circuiting, merge CORS response headers from cache with error response.

Pro: Most elegant solution
Con: Respecting CORS cache TTL, increased code complexity, possible edge cases.

@lonelycode
Copy link
Member

I think your second solution (certain conditions create an options request) is the most spec compliant.

IMO, the gateway should act just like any other user agent, that basically means that when options pass through is enabled, it should be constructing pre-flights on behalf of the inbound request and sending those on.

We can either make these conditional (I.e. on errors only), or make them constant, so they run on every request type.

Either way the pre-flight should go from gateway to upstream based on the real request made by the downstream user-agent. This basically means implementing the pre-flight spec into an http client.

When to trigger this client can then be a secondary option.

@letzya
Copy link
Contributor

letzya commented Mar 20, 2018

What about other response codes? they would just be blocked?
For instance:

  • When rate limit exceeded
  • When global rate limit exceeded 429
  • When quota exceeded
  • When access denided
  • Access to this API has been disallowed
  • Key has expired, please renew 401

Sorry, haven't thoroughly checked, this is off the top of my head

@asoorm asoorm self-assigned this Mar 20, 2018
@asoorm asoorm added the bug label Mar 20, 2018
@Meg4mi
Copy link

Meg4mi commented Dec 11, 2018

I'm facing the same issue when Tyk block the request and return a forbidden response. No CORS Headers because request never hit the upstream.

@altaurog
Copy link

altaurog commented Apr 4, 2019

I also have this issue with rate-limited 429 responses. Regarding solution 1, I recall that with "CORS": {"enable": true, "options_passthrough": true} we got header duplication in the response, which wreaked havoc with the browser.

@stale
Copy link

stale bot commented Mar 25, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs, please add comments to this ticket if you would like it to stay open. Thank you for your contributions.

@stale stale bot added the wontfix label Mar 25, 2020
@stale stale bot closed this as completed Jun 4, 2020
@chris-fewtrell
Copy link

not stale (ZD ref 11458) added TT-955

@armujahid
Copy link
Contributor

@andyo-tyk andyo-tyk changed the title bug: CORS options_passthrough on Non OPTIONS requests [TT-955] bug: CORS options_passthrough on Non OPTIONS requests Mar 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants