We have a strange CORS error with our API under Cloudflare Access. If we turn Cloudflare off from DNS settings the issue fixes.
The API is a Flask app with Flask-restplus. I’ve added flask-cors and this code to make sure it will add headers:
CORS(
app, origins="*", allow_headers=[
"Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
supports_credentials=True, intercept_exceptions=False
)
Also, we add headers in nginx for both location /api/
and location /
like:
map_hash_max_size 262144;
map_hash_bucket_size 262144;
map $http_origin $origin_allowed {
default 0;
https://00000000000000000000000.Cloudflareaccess.com 1;
https://00000000000000000000000.com 1;p
# ... add more allowed origins here
}
map $origin_allowed $origin {
default "";
1 $http_origin;
}
add_header 'Access-Control-Allow-Origin' $origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' $origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
An api POST call /api/auth/login
return 200 with the below headers that is fine.
Request URL: https://000000000.com/api/auth/login
Request Method: POST
Status Code: 200 OK
Remote Address: 104.25----
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true, true
Access-Control-Allow-Headers: Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE,PATCH
Access-Control-Allow-Origin: https://000000000.com, https://000000000.com
CF-RAY: -------
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Thu, 11 Jul 2019 21:04:39 GMT
Expect-CT: max-age=604800, report-uri="https://report-uri.Cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: Cloudflare
Transfer-Encoding: chunked
Vary: Origin
Provisional headers are shown
Accept: application/json, text/plain, */*
Content-Type: application/json;charset=UTF-8
DNT: 1
Origin: https://000000000.com
Referer: https://000000000.com/admin/login
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
{email: "-------", password: "----------"}
email: "------------"
password: "------------"
The only strange thing is that our domain repeated twice in Access-Control-Allow-Origin
. I’m not sure if it’s because of the map
in nginx setting. But I was tried to add single input there (both our domain and Cloudflareaccess) without map that doesn’t fix the issue.
Ok, Then we call our /api/admin/users
by ajax POST on the same page. It will generate three requests on the browsers!
1- users
with GET
that return 302
Request URL: https://000000000.com/api/admin/users
Request Method: GET
Status Code: 302 Moved Temporarily
Remote Address: 104.25.-----
Referrer Policy: no-referrer-when-downgrade
CF-RAY: -------
Connection: keep-alive
Content-Type: text/html
Date: Thu, 11 Jul 2019 21:04:39 GMT
Expect-CT: max-age=604800, report-uri="https://report-uri.Cloudflare.com/cdn-cgi/beacon/expect-ct"
Location: https://000000000.Cloudflareaccess.com/cdn-cgi/access/login/000000000.com?kid=e--------4cc26b733e1664c20&redirect_url=%2Fapi%2Fadmin%2Fusers&meta=&v=5d27a458
Server: Cloudflare
Transfer-Encoding: chunked
Vary: Accept-Encoding
Provisional headers are shown
DNT: 1
Referer: https://000000000.com/admin/users
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
2- ‘users’ with POST
that return 302
Request URL: https://000000000.com/api/admin/users
Request Method: POST
Status Code: 302 Moved Temporarily
Remote Address: 104.25----
Referrer Policy: no-referrer-when-downgrade
CF-RAY: 4f4d-------
Connection: keep-alive
Content-Type: text/html
Date: Thu, 11 Jul 2019 21:04:39 GMT
Expect-CT: max-age=604800, report-uri="https://report-uri.Cloudflare.com/cdn-cgi/beacon/expect-ct"
Location: https://000000000.Cloudflareaccess.com/cdn-cgi/access/login/000000000.com?kid=e768569ca9-----------e1664c20&redirect_url=%2Fapi%2Fadmin%2Fusers&meta=&v=5d27a458
Server: Cloudflare
Transfer-Encoding: chunked
Vary: Accept-Encoding
Provisional headers are shown
Authorization: --------------
DNT: 1
Origin: https://000000000.com
Referer: https://000000000.com/admin/users
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
3- a Cloudflareaccess OPTION
that return 200
Request URL: https://000000000.Cloudflareaccess.com/cdn-cgi/access/login/000000000.com?kid=e768569---------664c20&redirect_url=%2Fapi%2Fadmin%2Fusers&meta=&v=5d27a458
Request Method: OPTIONS
Status Code: 200
Remote Address: 104.16.-----
Referrer Policy: no-referrer-when-downgrade
Provisional headers are shown
Access-Control-Request-Headers: authorization,dnt
Access-Control-Request-Method: GET
DNT: 1
Origin: https://000000000.com
Referer: https://000000000.com/admin/users
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
kid: e768569c---------3e1664c20
redirect_url: /api/admin/users
meta:
v: ---------
The only difference between /api/auth/login
and /api/admin/users
is that we set header: {'Authorization': VALUE}
for the request.
Any idea what is the issue and how we could fix it? Why /api/auth/login
is ok from same origin but /api/admin/users
is not?
Thank you