CORS request redirect blocked by browsr - redirect

Running into an issue with CORS and redirect, here is the simplified flow:
Browser ---> K8 NGINX Ingress Controller ---> Service
|
|
Oauth Proxy
From Chrome developer tools: Preflight
General:
Request URL: https://yyyy
Request Method: OPTIONS
Status Code: 204
Remote Address: x.x.x.x:443
Referrer Policy: strict-origin-when-cross-origin
Request headers Preflight
:authority: yyyy
:method: OPTIONS
:path: /api
:scheme: https
accept:*/*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
access-control-request-headers: x-requested-with
access-control-request-method: GET
cache-control: no-cache
origin: https://xxxx
pragma: no-cache
referer: https://xxxx
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
Response Headers: Preflight
access-control-allow-credentials: true
access-control-allow-headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization
access-control-allow-methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
access-control-allow-origin: https://xxx
access-control-max-age: 1728000
content-length: 0
date: Mon, 06 Feb 2023 13:47:36 GMT strict-transport-security: max-age=15724800; includeSubDomains
Original Request: Headers
:authority: yyyy
:method: GET
:path: /api
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cache-control: no-cache origin: https://xxxx
pragma: no-cache
referer: https://xxxx
sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 x-requested-with: XMLHttpRequest
General
Request URL: https://yyy/a/api/a/a?=abc
Request Method: GET
Status Code: 302
Referrer Policy: strict-origin-when-cross-origin
Response Headers:
content-length: 138
content-type: text/html
date: Mon, 06 Feb 2023 13:47:36 GMT
location: https://yyyy/oauth2/start?rd=%2Fa%2Fapi%2Fs%2Fb%3Fx%3D1
Browser Blocks:
Access to XMLHttpRequest at 'https://yyyy from origin 'https://xxxx has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
Steps taken so far:
Read many SO questions for a match including this:
Chrome cancels CORS XHR upon HTTP 302 redirect
The way I understand this article: https://github.com/monmohan/cors-tutorial-practical/tree/master/issue
is that if the CORS request redirect with 3XX, then the browser should follow the redirect, but that is not happening
Read Mozilla docs:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin
Tried to follow this three part blog series and its associated github exercise:
https://software-factotum.medium.com/cross-origin-resource-sharing-a-hands-on-tutorial-fb19748cb3b7

The sequence when making a preflighted request to a URL that gets a redirect response is:
The browser makes a preflight OPTIONS request to A
The server must respond with CORS permission
The browser makes the real request to A
The server must respond with CORS permission and the redirect directive to B
The browser makes a preflight OPTIONS request to B
The server must respond with CORS permission
The browser makes the real request to B
The server must response with CORS permission and the data
It isn't entirely clear from your examples, but your sequence appears to be failing at step 4, where you are responding with the redirect directive but without CORS permission.

Related

Access-Control-Allow-Origin equals origin but the browser still denies access... why?

I have an application (React SPA) that calls a bunch of servers on different subdomains of the application domain, i.e.:
the web app sits at foo.bar.com,
and talks to api.foo.bar.com and media.foo.bar.com.
When accessing api.foo.bar.com, I get an error from the browser (be it Edge, Chrome, or Firefox) telling me that the origin (foo.bar.com) is different from the value of the Access-Control-Allow-Origin response header. However, by inspection of the response, they are the same:
(I unfortunately have to obfuscate the address.)
Those apps are hosted on Kubernetes; the ingress is NGINX, and it's is not providing CORS (cors-enabled annotation is false). Both applications (api and media) are Express apps, and both have the same CORS configuration allowing the specific origin.
I'm wondering if this has something to do with the redirect - the call to the media... endpoint returns a redirect (302) whose Location is a api... address.
Other than that, I have no clue what could be wrong. Something is, for sure, because all browsers agree that my request should be blocked (on account of the origin).
In all cases, I've checked the address multiple times for typos, ending forward-slashes, etc. I've called OPTIONS on those endpoints with cURL and Postman, using all headers or just a few. They always answer the correct address.
Additional information, as requested:
Preflight request:
OPTIONS /media/1.0.0/rtsp/hls?feedUrl=https%3A%2F%2Flive.monuv.com.br%2Fa1%2F14298.stream%2Fstr27%2Fchunklist.m3u8%3Fm_hash%3DkhV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%253D HTTP/2
Host: media.aiXXXXXXXXXXXXXX.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: feedurl
Referer: https://aiXXXXXXXXXXXXXXXX.com/
Origin: https://aiXXXXXXXXXXXXXXXX.com
DNT: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
TE: trailers
Preflight response:
HTTP/2 204 No Content
date: Fri, 08 Oct 2021 13:33:10 GMT
x-powered-by: Express
access-control-allow-origin: https://aiXXXXXXXXXXXXXXXXXX.com
vary: Origin
access-control-allow-credentials: true
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-headers: Content-Type, feedUrl
strict-transport-security: max-age=15724800; includeSubDomains
X-Firefox-Spdy: h2
Request
The preflight passes, and the browsers starts a "flight" request:
GET /media/1.0.0/rtsp/hls?feedUrl=https%3A%2F%2Flive.monuv.com.br%2Fa1%2F14298.stream%2Fstr27%2Fchunklist.m3u8%3Fm_hash%3DkhV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%253D HTTP/2
Host: media.aiXXXXXXXXXXXXXXXXXXXXX.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
feedUrl: https://live.monuv.com.br/a1/14298.stream/str27/chunklist.m3u8?m_hash=khV_hCnKG3nhaNCFaYZxBnoMz-99idQVHiQh80ADW78%3D
Origin: https://aiXXXXXXXXXXXXXXXX.com
DNT: 1
Connection: keep-alive
Referer: https://aiXXXXXXXXXXXXXXXXX.com/
Cookie: ory_kratos_session=MTYzMzYzODY1OHxEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiXXXXXXXXXXXXYVc1bkRDSUFJSHBtUWxsaWFsVlJhWGRTVGxSMmIzZHRkbTFqYm5CUlRWVkdkelpPWkRoWnXXXTyqwgK-0Pe0qtZHjNhfU-YoASjg3istMZi672swQ==
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
TE: trailers
Response
HTTP/2 302 Found
date: Fri, 08 Oct 2021 13:33:10 GMT
content-type: text/plain; charset=utf-8
content-length: 129
location: https://api.aiXXXXXXXXXXXXXXXXXX.com/media/1.0.0/hls/streams/19dd149d-f551-4093-b2aa-e5558388d545/hls.m3u8
x-powered-by: Express
access-control-allow-origin: https://aiXXXXXXXXXXXXXXXX.com
vary: Origin, Accept
access-control-allow-credentials: true
strict-transport-security: max-age=15724800; includeSubDomains
X-Firefox-Spdy: h2
At this response, the browser fails saying that the origin don't match the access-control-allow-origin.
(the first image was from Edge, since the log was more clear; this log is from Firefox)
Problem
The error message—I'm using dummy URLs and origins below—from the browser can be a bit confusing:
Access to XMLHttpRequest at 'https://api.example.com/' (redirected from 'https://media.example.com/') from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://example.com' that is not equal to the supplied origin.
The key here is that, as sideshowbarker hinted at in his comment, because your first preflighted request to https://media.example.com/ responds with a cross-origin redirect to https://api.example.com/, the browser performs another whole CORS access-control check for that resource. However, because the redirect resulting from the first preflighted request happens to be cross-origin, the browser sets the origin of the second preflight request (which the error message refers to as the "supplied origin"), not as https://example.com, but as the null origin!
Here's a rundown of what is likely happening:
Because https://api.example.com likely doesn't (and shouldn't!) allow the null, the second access-control check fails and you get that annoying CORS error.
Solution
Resist the temptation to allow the null origin on https://api.example.com/, as doing so has serious security ramifications: it amount to voiding the protection that the Same-Origin Policy provides.
Instead, you should get rid of that redirect from https://media.example.com/ to https://api.example.com/ and make your frontend request the https://api.example.com/ resource directly.
Alternatively, if you cannot completely get rid of the redirect but you can change its destination, make it a same-origin redirect (from somewhere https://media.example.org to elsewhere on https://media.example.org).

Uber Universal Deep Link giving CORS error

I'm trying to develop with universal deep links. When the user has the Uber app installed, everything works as expected. But if not, the user ends up at a page with "Open in the Uber app" and "Download Uber" links, both of which do nothing. In the console, a CORS error is reported. This includes opening the "example universal deep link to Uber HQ" given in the developer docs. Is this a known issue or is there something I can do to work around it? I'd like my users to be able to use the deep link without this poor experience.
Request headers (for ul-min.a36a5e.js):
GET /web-mobile-client/js/ul-min.a36a5e.js HTTP/1.1
Host: d34odocr7rsfu1.cloudfront.net
Connection: keep-alive
Origin: https://m.uber.com
Sec-Fetch-Dest: script
User-Agent: Mozilla/5.0 (Linux; Android 8.0.0; Moto Z (2)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36
Accept: */*
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://m.uber.com/ul/?action=setPickup&pickup=my_location&dropoff%5Bformatted_address%5D=Uber%20HQ%2C%20Market%20Street%2C%20San%20Francisco%2C%20CA%2C%20USA&dropoff%5Blatitude%5D=37.775231&dropoff%5Blongitude%5D=-122.417528&_ga=2.28187893.830846417.1581952272-1919070024.1581952272
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ja;q=0.8
Response Headers
HTTP/1.1 403 Forbidden
Content-Type: application/xml
Transfer-Encoding: chunked
Connection: keep-alive
Date: Tue, 18 Feb 2020 17:29:53 GMT
Server: AmazonS3
X-Cache: Error from cloudfront
Via: 1.1 c66a9c8f31dcbd61d052f66d50b6d87c.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: LAX3-C1
X-Amz-Cf-Id: 00Y21qP41BPYaywzR6BHA0BC-5ctAe03xFKBgOBgDKupwlaN-2IzLA==

CORS from Firebase Hosting to REST api to other sub-domain

I have hosted my web-app on "Firebase Hosting" on my own custom domain for eg:- webapp.example.com. I have enabled CORS so that browser wont block it.
My REST services are hosted on another sub-domain eg:- api.example.com
Now when I am calling API from my web-app it says "Failed to load response" and fails.
Status code is 200 though.
Response Headers:
Access-Control-Allow-Headers: Origin,X-Requested-With,Content-Type,Accept
Access-Control-Allow-Methods: POST,GET,PUT,OPTIONS,DELETE,PATCH
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Allow: GET, HEAD, POST, TRACE, OPTIONS
Connection: close
Content-Length: 0
Date: Sun, 28 Apr 2019 09:37:30 GMT
Server: Apache-Coyote/1.1
Request Headers
Access-Control-Request-Headers: content-type,x-referral
Access-Control-Request-Method: GET
Origin: https://webapp.example.com
Referer: https://webapp.example.com/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Any idea why this is happening or how should I fix it.

CORS restrictions even when headers are applied in java server backend

So I have a REST Service based on Java EE which returns every request with this function in addition to set the CORS Headers:
protected Response.ResponseBuilder addRequiredHeaders(Response.ResponseBuilder rb) {
return rb
.header("Access-Control-Allow-Origin", "http://localhost:8080")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE")
.header("Access-Control-Allow-Headers", "Content-Type, *");
}
Now when I'm making a request from the frontend I'm still getting some CORS related issues. Here's the code for the request from the frontend
fetch (apiURL + "/api/rest/users/create", {
body: JSON.stringify(payload),
headers: {
"content-type": "application/json"
},
method: "POST",
mode: "cors",
})
.then((response) => {
...
}.catch((err) => {
...
}
Here is the exact error message:
Failed to load http://localhost:8888/java_ee_project/api/rest/users/create:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Here is some additional information from the network tab in the devtools from the browser
General
Request URL: http://localhost:8888/java_ee_project/api/rest/users/create
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 127.0.0.1:8888
Referrer Policy: no-referrer-when-downgrade
Response Headers
Allow: POST, OPTIONS
Connection: keep-alive
Content-Length: 13
Content-Type: text/plain;charset=UTF-8
Date: Fri, 04 May 2018 23:10:04 GMT
Server: WildFly/11
X-Powered-By: Undertow/1
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
DNT: 1
Host: localhost:8888
Origin: http://localhost:8080
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1
When I'm executing the same request with Postman everything works fine so I would be very gladful for any help or information about this problem.
Somehow the solution via the added responsebuilder function is not working properly.
Using the second option from http://www.codingpedia.org/ama/how-to-add-cors-support-on-the-server-side-in-java-with-jersey/ with the cors response filter it's working now.

rest-assured OAuth 1.0a How can I insert both Header and Query params in the request

Magento's 1.9 REST API needs both Authorization Header and oauth query params, but oauth() only allows for either OAuthSignature.HEADER, or QUERY_STRING
given().auth().oauth(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN,
SECRET_TOKEN,OAuthSignature.HEADER)
I tracked the code down to com.jayway.restassured.internal.httpAuthConfig.process(..), but I am not sure what to do from here.
Q: Is there a filter or some method that would allow me to force both?
TL;DR
I started by referring to this: How to use POSTMAN rest client with magento REST api with Oauth. How to get Token and Token Secret?
The last statement
Note, you must check the "Add params to header" checkbox in order for Magento REST calls to work properly.
Using Postman, OAuth 1.0 GET works when I check the box and fails
when I don't, with 403 access denied. This is the same response I get when I use OAuthSignature.QUERY_STRING in rest-assured.
WORKS: Sent from Postman (add params to header)
GET /api/rest/products?oauth_consumer_key=<my-consumer-key>&oauth_token=<my-oauth-token>&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1471929347&oauth_nonce=LJ3o2K&oauth_version=1.0&oauth_signature=0Any8rQ+XjbnWcdXmpHFujg1V7o= HTTP/1.1
Host: dockerized-magento.local
Connection: keep-alive
Authorization: OAuth oauth_consumer_key="<my-consumer-key>",oauth_token="<my-oauth-token>",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1471996573",oauth_nonce="ElK9Fx",oauth_version="1.0",oauth_signature="SvDfMxrWj1O0P2%2FWPOomEVEb93c%3D"
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
Postman-Token: 9348e805-3c6f-54d7-082f-a1458164725d
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
rest-assured OAuthSignature.QUERY_STRING
Doesn't Work: OAuthSignature.QUERY_STRING
GET /api/rest/products?oauth_nonce=-316324336&oauth_signature=TlANZu5ogxowYJCpr2V7W448tjw%3D&oauth_token=<my-oauth-token>&oauth_consumer_key=<my-consumer-key>&oauth_timestamp=1471996938&oauth_signature_method=HMAC-SHA1&oauth_version=1.0 HTTP/1.1
Accept: */*
Content-Length: 0
Host: dockerized-magento.local
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.1 (Java/1.8.0_77)
Accept-Encoding: gzip,deflate
RESP: {"messages":{"error":[{"code":403,"message":"Access denied"}]}}
Same failed response using Postman with out "add params to header")
Doesn'T WORK: Sent from Postman (NO - add params to header)
GET /api/rest/products?oauth_consumer_key=<my-consumer-key>&oauth_token=<my-oauth-token>&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1471976516&oauth_nonce=OTWTNW&oauth_version=1.0&oauth_signature=Dsh5TEErEC9rMbKakta1v2E7ZTw= HTTP/1.1
Host: dockerized-magento.local
Connection: keep-alive
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
Postman-Token: f9800e1c-b259-f025-cf48-68e483283869
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Response: {"messages":{"error":[{"code":403,"message":"Access denied"}]}}
Mistake made, HEADER option works fine.
The Postman link above, which works fine and was a great help, led me to believe I needed both url params and headers. I went back to postman and deleted the url params after adding params to headers. This worked fine.
I went back and found my consumer keys were wrong.
Tip: Magento Consumer Keys and Secret are not "copyable", use firebug!