CORS: Access-Control-Allow-Origin is missing from proxied request

Hi,

I’ve logged a support ticket about this 6 days ago to which I received an initial reply, but no further follow-up.
So I’m posting the issue here as well in the hopes it might ring familiar to someone.

A resource hosted on Azure storage https://hcdaikineventsapp.blob.core.windows.net/cdn/hc/favicon/site.webmanifest needs to be fetched from a website on another domain, i.e.: this is a CORS request.
This works fine when using this direct link.
Cloudflare is used as the CDN that sits in front of the Azure resource, and as such the corresponding URL becomes https://daikin-cdn.hybridconferences.org/hc/favicon/site.webmanifest.
Doing the exact same request using this URL, a CORS error is thrown saying there is no Access-Control-Allow-Origin header in the response, and indeed, it’s not there.

This is the response when using the direct link.

Request URL: https://hcdaikineventsapp.blob.core.windows.net/cdn/hc/favicon/site.webmanifest
Request Method: GET
Status Code: 200 OK (from disk cache)
Remote Address: 127.0.0.1:7769
Referrer Policy: strict-origin-when-cross-origin

HTTP/1.1 200 OK
Content-Length: 458
Content-Type: text/plain; charset=utf-8
Content-MD5: UzIU2+Bt6NjqWFDUJzThfw==
Last-Modified: Sat, 31 Oct 2020 06:33:20 GMT
ETag: 0x8D87D66DBE01D2D
Vary: Origin
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: e39362cc-401e-004f-0177-9abd78000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Access-Control-Allow-Origin: https://cdpn.io
Access-Control-Allow-Credentials: true
Date: Thu, 26 Aug 2021 12:37:22 GMT

Referer: https://cdpn.io/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="92"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36

This is the request data using the Cloudflare link.

Request URL: https://daikin-cdn.hybridconferences.org/hc/favicon/site.webmanifest
Referrer Policy: strict-origin-when-cross-origin
age: 603
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400
arr-disable-session-affinity: true
cache-control: max-age=14400
cf-cache-status: HIT
cf-ray: 684d2b399da14c08-AMS
content-encoding: br
content-md5: UzIU2+Bt6NjqWFDUJzThfw==
content-type: text/plain; charset=utf-8
date: Thu, 26 Aug 2021 12:47:28 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
last-modified: Sat, 31 Oct 2020 06:33:20 GMT
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=anyg2QlZtr7hIdFW9PaRSlLbVfq7pv8TcbygFKKz6c%2Fi9tdwimgeQ%2BxA6dep3QDCCUcVoOjNil%2BsLHO59qQ83NprJT8HgoQLwb8%2BfM0BjEOIDZsCNUtD0Rs0nk2y1VV3NCq7KN6Hj%2BWErUCLXNxji%2BOa"}],"group":"cf-nel","max_age":604800}
server: cloudflare
vary: Origin,Accept-Encoding
x-ms-blob-type: BlockBlob
x-ms-lease-status: unlocked
x-ms-request-id: 84a122c7-f01e-0070-2d77-9a1576000000
x-ms-version: 2009-09-19
:authority: daikin-cdn.hybridconferences.org
:method: GET
:path: /hc/favicon/site.webmanifest
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
origin: https://cdpn.io
referer: https://cdpn.io/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="92"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36

I have also made a codepen illustrating the issue here: https://codepen.io/ownerer/pen/wvewVOm
As you can see, the code is the exact same thing for both links, but somehow the Cloudflare scenario fails…
Why is this header being stripped? Any ideas?

Bump; anyone?

Accessing the resource directly does not give CORS headers. The example you gave there was from CodePen and you can see in the CORS headers too, Access-Control-Allow-Origin: https://cdpn.io
cdpn.iocodepen.io

Here are the headers I got doing a direct request:

HTTP/1.1 200 OK
Content-Length: 458
Content-Type: text/plain; charset=utf-8
Content-MD5: UzIU2+Bt6NjqWFDUJzThfw==
Last-Modified: Sat, 31 Oct 2020 06:33:20 GMT
ETag: 0x8D87D66DBE01D2D
Vary: Origin
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 1d56af48-301e-0004-287b-9d4b7e000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Date: Mon, 30 Aug 2021 08:47:31 GMT

I suggest you read the MS Documentation on adding CORS headers to blob storage: https://docs.microsoft.com/en-us/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services

1 Like

Well of course accessing the resource directly doesn’t give CORS headers…
That’s what Cloudflare tech support did with a cURL request in the support ticket I logged, told them that as well.
That’s the whole reason I set up the codepen, to illustrate a request to the resource from a different domain.
The fact that, as you describe, you get the Access-Control-Allow-Origin: https://cdpn.io header using the codepen is because I have set up CORS on the Azure blob storage; it would also just not work otherwise…

So again: Cloudflare must be stripping that header somewhere for some reason, it’s the only logical conclusion I can come to.

So to summarize:

  • The point of the codepen is doing a request to the resource from another domain.
  • I’ve temporarily set up CORS for codepen, for testing purposes.
  • Requesting the resource from codepen using the direct Azure link works. You get the corresponding Access-Control-Allow-Origin header. This is expected. This is what should happen.
  • Requesting the exact same resource using the exact same code, but through Cloudflare, fails.

Seeing as Cloudflare is the only variable that is different in that setup, I suspect the problem to be Cloudflare-related. But I have no idea why, that’s what I’m trying to figure out.

2235986 @MoreHelp

If the Origin is not emitting CORS response headers, Cloudflare will not either. Cloudflare in fact shards the cache based on the Origin request header.

If I make a request to your Origin with an Origin request header, I do not see CORS response headers, except for https://cdpn.io.

% curl --dump-header - -o /dev/null --silent -H "Origin: https://www.example.com" https://hcdaikineventsapp.blob.core.windows.net/cdn/hc/favicon/site.webmanifest
HTTP/1.1 200 OK
Content-Length: 458
Content-Type: text/plain; charset=utf-8
Content-MD5: UzIU2+Bt6NjqWFDUJzThfw==
Last-Modified: Sat, 31 Oct 2020 06:33:20 GMT
ETag: 0x8D87D66DBE01D2D
Vary: Origin
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 8242309d-901e-0022-1f08-9f2041000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Date: Wed, 01 Sep 2021 08:05:01 GMT

Is there a value of Origin that you are not getting CORS responses for when accessed via Cloudflare?

2 Likes

Hi Michael, thanks for getting back to me.

Yes there is: none of them work (a couple are set, among which https://cdpn.io)
Direct access: Access-Control-Allow-Origin is returned as expected.
Cloudflare access: no header is returned.

The cURL equivalents would be:
Direct access:
curl --dump-header - -o /dev/null --silent -H "Origin: https://cdpn.io" https://hcdaikineventsapp.blob.core.windows.net/cdn/hc/favicon/site.webmanifest
result:

HTTP/1.1 200 OK
Content-Length: 458
Content-Type: text/plain; charset=utf-8
Content-MD5: UzIU2+Bt6NjqWFDUJzThfw==
Last-Modified: Sat, 31 Oct 2020 06:33:20 GMT
ETag: 0x8D87D66DBE01D2D
Vary: Origin
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 4457a7d6-601e-0071-1f1a-9f3e74000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
Access-Control-Allow-Origin: https://cdpn.io
Access-Control-Allow-Credentials: true
Date: Wed, 01 Sep 2021 10:17:15 GMT

Cloudflare access:
curl --dump-header - -o /dev/null --silent -H "Origin: https://cdpn.io" https://daikin-cdn.hybridconferences.org/hc/favicon/site.webmanifest
result:

HTTP/2 200
date: Wed, 01 Sep 2021 10:19:12 GMT
content-type: text/plain; charset=utf-8
content-md5: UzIU2+Bt6NjqWFDUJzThfw==
last-modified: Sat, 31 Oct 2020 06:33:20 GMT
vary: Origin,Accept-Encoding
x-ms-request-id: 69dd22e9-901e-005a-031a-9f8a50000000
x-ms-version: 2009-09-19
x-ms-lease-status: unlocked
x-ms-blob-type: BlockBlob
arr-disable-session-affinity: true
cache-control: max-age=14400
cf-cache-status: HIT
age: 105
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi                                                            /beacon/expect-ct"
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=vz                                                            0iVj7P6DWT8vAhBroFBipvCrWxQSVV98AwBj%2F8VVySWqOFvDiJweAv85hmmoqbQRB0mN97cx1h%2B4                                                            HDvSbfOoHoM9E34TZyawOtJ4zqIouOZTKNtyhS3Oof7xnPEV3LwPTNuZHB%2BmrVi0QSY2Z%2FnAAj"}                                                            ],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
server: cloudflare
cf-ray: 687dc249880a0bf5-AMS
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400,                                                             h3=":443"; ma=86400

So either Cloudflare is stripping the Origin header from the request to the Azure resource, causing CORS to fail in Azure; or it’s stripping the Access-Control-Allow-Origin header from the response before returning it to the client.
I’m at a loss honestly :confused:

Getting there myself!

Do you have any Page Rules, Transform Rules or Workers Routes that impact this URL?

Is the DNS for daikin-cdn a CNAME to hcdaikineventsapp.blob.core.windows.net, or is something else involved?

2 Likes

I bow my head in deep deep shame…
Thanks Michael, you made me look in the right direction.

Looking at the DNS config I realized the CNAME actually does not point directly at the blob storage, but at an Azure Function App proxy that’s fronting it. CORS had not been set up for that, sigh.

I guess that’s what happens when you’re spread too thin: you make assumptions; and we all know what they’re the mother of…

Thank you for thinking along and sorry for wasting your time with this!

2 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.