CORS issue on/in nodejs and react application via cloudflare tunnel

Hi, So the scenario is as follows: 1. Have my frontend and backend both under a single docker-compose.yml along with a cloudflare tunnel 2. The tunnel has then two public hostnames (CNAMEs) mapped to frontend.example.com -> frontend service name:port and backend.example.com -> backend service name:port 3. These two are working fine individually when I tested locally and after serving via cloudflare tunnel Now the issue is: 1. For the sake of simplicity and testing I enabled "cloudflare access" and CORS settings are (refer screenshot 1) 2. Then whenever I'm trying to send a request from frontend to the backend, I'm getting the cloudflare access screen for response (refer screenshot 2) 3. So again for the sake of simplicity I removed my backend.example.com from the cloudflare access and then all of a sudden I'm am completely getting CORS error My backend CORS config is:
app.use(cors({
origin: 'https://frontend.example.com
}));
app.use(cors({
origin: 'https://frontend.example.com
}));
and frontend api baseurl is:
const API = axios.create({
baseURL: 'https://backend.example.com'
)}
const API = axios.create({
baseURL: 'https://backend.example.com'
)}
I am kind of stuck here as I am a little new to CORS and related stuff, if anyone can help would be appreciated.
No description
No description
20 Replies
dhakkad
dhakkadOP12mo ago
If more details are required, I can provide those.
Cyb3r-Jak3
Cyb3r-Jak312mo ago
That that response in screenshot 2 from the options requests?
dhakkad
dhakkadOP12mo ago
@Cyb3r-Jok3 So, I was able to get it to work using app.options() after disabling the cloudflare waf/cloudfalre access on the backend and frontend sub-domains. What I wasn't able to achieve is and what I wanted to achieve is (at least I expected that it should work but for some reason, I wasn't able to get it to work as I'm not sure atm whether it is possible or not): 1. I wanted to use cloudflare waf/cloudflare access as the protection firewall for both my backend.example.com and frontend.example.com where both are running inside the same docker-compose.yml context and served via a single coudflared container in the same context. 2. My backend doesn't have a login/api-token system so I wanted to use cloudflare's waf as a protection layer and then using another IDP in front of it without worrying about the authentication+authorization on the backend side 3. When I enabled cf's waf on both frontend.example.com and backend.example.com I never got it working, always the error about CORS, even tried leaving the CORS on application level as "allow all origins" but idk I never got it working. I wanted to ask whether the thing I was trying to achieve is actually doable/possible or not? Also, fyi/fyr for these problems and possibly my lack of knowledge currently I'm serving both frontend and backend from same origin letting me still use cf's waf and removing all the CORS related complications or misconfigurations but I'm would love to know whether and how "what I was trying to achieve is possible or not" @Cyb3r-Jok3 sorry to ping you on this again, I just wanted to know whether it is possible or not, and if it is then what I am doing wrong?
Cyb3r-Jak3
Cyb3r-Jak312mo ago
Are you referring to WAF or access? Access should allow the OPTIONS header to go, but after you'll need to pass auth to be able to use the site. It would be easier if you make an access application that covers both frontend and backend domains otherwise, the users will have to login into access at somepoint to be able to auth to backend
dhakkad
dhakkadOP12mo ago
@Cyb3r-Jok3 Thanks for responding. So, I tried it again, now the setup is as follows: 1. CF Tunnel created 2. Two public hostnames under the single tunnel -> front.example.com and api.example.com Backend:
const http = require('http');
const path = require('path');
const express = require('express');
const app = express();
const cors = require('cors');
const server = http.createServer(app);

const homeRoute = require('./routes/homeRoute');
const uploadRoute = require('./routes/uploadRoute');
const notFoundRoute = require('./routes/notFoundRoute');

app.use(express.json());

const corsOptions = {
origin: 'https://front.example.com',
methods: 'GET,POST',
};

app.options('*', cors(corsOptions));
app.use(cors(corsOptions));

app.use('/', homeRoute);
app.use('/file', uploadRoute);
app.use(notFoundRoute);

server.listen(3000, '0.0.0.0', () => {
var addr = server.address();
console.log(`API is running and listening on -> ${addr.address}:${addr.port}`);
});

module.exports = server
const http = require('http');
const path = require('path');
const express = require('express');
const app = express();
const cors = require('cors');
const server = http.createServer(app);

const homeRoute = require('./routes/homeRoute');
const uploadRoute = require('./routes/uploadRoute');
const notFoundRoute = require('./routes/notFoundRoute');

app.use(express.json());

const corsOptions = {
origin: 'https://front.example.com',
methods: 'GET,POST',
};

app.options('*', cors(corsOptions));
app.use(cors(corsOptions));

app.use('/', homeRoute);
app.use('/file', uploadRoute);
app.use(notFoundRoute);

server.listen(3000, '0.0.0.0', () => {
var addr = server.address();
console.log(`API is running and listening on -> ${addr.address}:${addr.port}`);
});

module.exports = server
Frontend:
import axios from 'axios';

const API = axios.create({
baseURL: 'https://api.example.com'
});

export default API;
import axios from 'axios';

const API = axios.create({
baseURL: 'https://api.example.com'
});

export default API;
3. Both are served at front.example.com & api.example.com 4. To use cf's access protection, I created an app under -> Zero Trust > Access > Applications > "example" 5. Created (pic 1) multiple application domains 6. Created app policies and enabled github as IDP for the authentication/authorization 7. The security mechanism itself is working as expected 8. But as soon as enabled these security settings and went back to making requests from front.example.com to api.example.com, now got CORS errors (pic 2) I do want to use front.example.com & api.example.com separately with the same protection but I just cannot get it working. Currently, as a workaround serving both the frontend & backend on the same origin. Need advice on this scenario; willing to provide more information.
No description
No description
Cyb3r-Jak3
Cyb3r-Jak312mo ago
Thanks for the info. I’ll see if I can recreate this later today
dhakkad
dhakkadOP12mo ago
Great, thank you 🙏
Cyb3r-Jak3
Cyb3r-Jak312mo ago
Would you be able to share your docker compose file as well? Saves me trying to recreate it
dhakkad
dhakkadOP12mo ago
Will this work?
version: '3.8'

services:
wordpress-cf-tunnel:
image: cloudflare/cloudflared
restart: unless-stopped
command: tunnel run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN}
logging:
driver: local
options:
max-size: "10m"
max-file: "3"

api:
build:
context: .
dockerfile: dev.Dockerfile
volumes:
- ./backend/api:/usr/src/app
ports:
- "3333:3000"

frontend:
build:
context: ./frontend
dockerfile: dev.Dockerfile
volumes:
- ./frontend:/app
restart: unless-stopped
ports:
- 8080:3000
environment:
- CHOKIDAR_USEPOLLING=true
logging:
driver: local
options:
max-size: "10m"
max-file: "3"
version: '3.8'

services:
wordpress-cf-tunnel:
image: cloudflare/cloudflared
restart: unless-stopped
command: tunnel run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN}
logging:
driver: local
options:
max-size: "10m"
max-file: "3"

api:
build:
context: .
dockerfile: dev.Dockerfile
volumes:
- ./backend/api:/usr/src/app
ports:
- "3333:3000"

frontend:
build:
context: ./frontend
dockerfile: dev.Dockerfile
volumes:
- ./frontend:/app
restart: unless-stopped
ports:
- 8080:3000
environment:
- CHOKIDAR_USEPOLLING=true
logging:
driver: local
options:
max-size: "10m"
max-file: "3"
Cyb3r-Jak3
Cyb3r-Jak312mo ago
So I think I got it to work at least I get a 404 error and not a CORS error
dhakkad
dhakkadOP12mo ago
Oh, so the most recent try from my side was with these disabled altogether.
No description
dhakkad
dhakkadOP12mo ago
Before, with the same config as I mentioned above and the one you tested. I enabled the CORS at the application level (on cf's side) and then I specified origin as front.example.com and and just for a hit and trial I also added api.example.com but I never got it working with this as well. But let me try one more time and I'll provide an update.
dhakkad
dhakkadOP12mo ago
So, I tried this and got the same CORS error.
No description
Cyb3r-Jak3
Cyb3r-Jak312mo ago
Firefox or Chrome?
dhakkad
dhakkadOP12mo ago
Edge And also, when I did this (refer to the app's CORS settings), means allowed all origins. Then I got the "Cloudflare Sign in page in response" and data was sent from frontend but never got received on the backend because of backend only allows from front.example.com and I believe that because of cf's sign in response page the cf's logic in between is not letting the data to got back with correct origin, or something similar is happening.
No description
No description
dhakkad
dhakkadOP12mo ago
First of all, thanks a lot for putting in this much effort for this. So, I looked at your setup, all the things are same but the only difference is idk how you managed to save the CORS settings with just (refer to screenshot) because I am getting an error with the same.
No description
dhakkad
dhakkadOP12mo ago
Also, I just noticed, I don't think I need to even enable "Access-Control-Allow-Credentials". @Cyb3r-Jok3 Just to add here. At first, I thought the issue was with my backend CORS settings/config or my frontend's baseurl but later (as mentioned above as well) and after trying a few different things, when I disabled Cloudflare's access on both the subdomains api.example.com and front.example.com these are working fine. And when cf access was disabled I even tried changing the CORS allowed origin in the backend to front-test.example.com and still sending a request from front.example.com just to mimic a scenario and check whether my CORS settings are correct or not and by logic the backend did not allow requests from front.example.com as it is now only configured to allow the request from front-test.example.com. So, I believe the issue is with how CF access and CORS are not allowing the same thing to be achievable. IDK what I'm missing.
Cyb3r-Jak3
Cyb3r-Jak312mo ago
I believe I did the CORs settings by saving origins then allowing creds toggle. I'm also not sure what else it could be and can't fully create your situation
Want results from more Discord servers?
Add your server