Overwrite all response headers with Express - node.js

I'm trying to build a Node/Express server that essentially acts as a middleman server and logs any requests that come in, then forwards the request to the destination server, and forwards back any responses that come from the destination server. The goal is to be as "transparent as possible, making it seem as if there is no middleman server at all.
The problem I'm having is that my express server seems to be dumping in a bunch of unnecessary headers in the response from the destination server.
In my app.js I have some (a lot of) middlewares that are useful for my app in general but seems to inject headers in the response:
app.use(rateLimiter);
app.use(helmet());
app.use(xss());
app.use(mongoSanitize());
app.use(nocache());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
Then I have my middleware endpoint that receives the request, forwards it, and returns the response:
exports.createLink = async (req, res, next) => {
try {
const url = 'https://destination-endpoint.com';
const options = {
url: url,
};
request( options, function(err, remoteResponse, remoteBody) {
res.writeHead(remoteResponse.statusCode, {...remoteResponse.headers});
return res.end(remoteBody);
});
} catch (error) {
console.log(error);
next(error);
}
};
If I hit my middleman I get the response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Vary: Accept-Encoding
Access-Control-Allow-Credentials: true
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
date: Sun, 24 Jan 2021 05:23:07 GMT
X-RateLimit-Reset: 1611465796
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
X-DNS-Prefetch-Control: off
Expect-CT: max-age=0
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: no-referrer
X-XSS-Protection: 0
Surrogate-Control: no-store
cache-control: no-cache, private
Pragma: no-cache
Expires: 0
server: nginx/1.14.2
content-type: text/plain; charset=UTF-8
transfer-encoding: chunked
connection: close
x-request-id: 864b8443-5fe2-498e-8e88-662035afe6c7
x-token-id: d0cb94e2-9c87-4d6e-b32a-11fcc698ad2c
set-cookie: laravel_session=tBlSCeel0OFIR5pL9C6f02JfXGqoyg3SN6BH6jjG; expires=Sun, 24-Jan-2021 07:23:07 GMT; Max-Age=7200; path=/; httponly
{
"foo": "bar"
}%
While if I hit the endpoint directly I just get this:
HTTP/1.1 200 OK
Server: nginx/1.14.2
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Request-Id: 1f033b57-4a2f-48a1-82b3-41bce6e2d748
X-Token-Id: d0cb94e2-9c87-4d6e-b32a-11fcc698ad2c
Cache-Control: no-cache, private
Date: Sun, 24 Jan 2021 05:24:28 GMT
Set-Cookie: laravel_session=MdOGJ18iDU28XLmNYXf5T2RxSa25KxqFisxzCBzR; expires=Sun, 24-Jan-2021 07:24:28 GMT; Max-Age=7200; path=/; httponly
{
"foo": "bar"
}%
As you can see there is a lot of extra stuff added to the header. Some of it may be solvable by removing middlewares/etc. but I think the bigger issue is that I want to return the response from the destination server AS IS no matter what. I found that I can delete the current headers before sending it like this:
request( options, function(err, remoteResponse, remoteBody) {
const headers = res.getHeaders();
for (const head in headers){
res.removeHeader(head);
}
res.writeHead(remoteResponse.statusCode, {...remoteResponse.headers});
return res.end(remoteBody);
});
But that seems very heavy handed, there has to be an easier way to overwrite/set all response headers to exactly what I need. So my overall question is:
How do I return the response from the request to the destination server EXACTLY as is?

Related

No 'Access-Control-Allow-Origin' header is present on the requested resource while using Passport for google authenticate in Nodejs

I am trying to authenticate with google using a passport IN MERN app.
Getting the below error but if I open the link available in below error in a new tab I am able authenticate with google.
Only issue is with below error
Error :
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com' (redirected from 'http://localhost:8000/auth/google') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS Config
app.use(cors({
origin: ["http://localhost:3000"," https://accounts.google.com"],
methods: "GET,POST,PUT,DELETE",
credentials: true,
}));
Passport routes
CLIENT_URL=http://localhost:3000
router.get("/google", passport.authenticate("google", ["profile"]));
router.get("/google/callback", passport.authenticate("google", {
successRedirect: process.env.CLIENT_URL,
failureRedirect: "/login/failed",
}));
router.get("/login/failed", (req, res) => {
res.status(401).json({
error: true,
message: "Log in failure",
});
});
Client req using Axios
REACT_APP_API_URL=http://localhost:8000
export const googleLoginReq = async () => {
try {
let res = await axios.get(`${REACT_APP_API_UR}/auth/google`, { withCredentials: true });
return res.data;
} catch (error) {
console.log(error);
}
};
Headers
General:
Request URL: https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com
Request Method: GET
Status Code: 200
Referrer Policy: strict-origin-when-cross-origin
Response headers:
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-encoding: gzip
content-security-policy: require-trusted-types-for 'script';report-uri /cspreport
content-security-policy: script-src 'report-sample' 'nonce-TOmywtPu0Qo8iQCEZhMnTw' 'unsafe-inline' 'unsafe-eval';object-src 'none';base-uri 'self';report-uri /cspreport
content-type: text/html; charset=utf-8
cross-origin-opener-policy-report-only: same-origin; report-to="coop_gse_qebhlk"
date: Wed, 25 Jan 2023 10:01:03 GMT
expires: Mon, 01 Jan 1990 00:00:00 GMT
p3p: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
pragma: no-cache
report-to: {"group":"coop_gse_qebhlk","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gse_qebhlk"}]}
server: GSE
set-cookie: __Host-GAPS=1:WBh43ekzNFz-U7PJu6wrySL4P0fJVw:-8nse8F4eB1X5yrO;Path=/;Expires=Fri, 24-Jan-2025 10:01:02 GMT;Secure;HttpOnly;Priority=HIGH
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
Request headers:
:authority: accounts.google.com
:method: GET
:path: /o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-IN,en-US;q=0.9,en;q=0.8
cookie: __Secure-3PAPISID=0fADWvGybtHw6h4E/AuZfyvMRCsCGQG4m9; __Secure-3PSID=TAgcETHlEPmlnVokgxJP67RdvdDCwLo6zS5s8W_yA_tnNn79ks2clkRgFmsvP0yZRult_A.; __Host-3PLSID=o.chat-dl.google.com|o.chat.google.com|o.console.cloud.google.com|o.drive.google.com|o.mail.google.com|o.meet.google.com|o.myaccount.google.com|s.IN|s.youtube:TAgcET_mZKiKd0P8KBaXK00vnWmuYQPOt8sRxUc75wk7hbKaEbtuam5S-oCMNPtkvpnT_w.; NID=511=ui5rQ6D8-KrHAUOn491ZvzQP7VdaQ-r94ktEYHfqHSWwWXK9E29AWZYBZMZRE8g9Zesepsp6c6lp-VjKU1dUWus4ICU9FkArFbf7bw5E6wQFcb9mOasQA0yV1qPgVErv49i1GLrgpHc373TwTqgC1Oah1nme4oaN2VBBN-r5YyAXun1eL4P-u3Iw7W6SV7ExIqnkunp4bQoG9ThcP5DjlkyDy14sK_YuV5EZwGIm9P6a18SsDcHDE2quUps7_LdjcE_CRL_OcB8v53R-Y9msRdxrBNGhY23yvgFbVkANBh5wKElpTvfTG7vxrDxZW_8Ol3LcM_wmKdD1ePuPHQrh4v1wQ29i16Vd0Z7obEEfP2hdig; LSOLH=AH+1Ng3ry+24BKCDnw1k/j8gBn5vXNTEUY4wwBo52xPp9smoYZt/jdHVLmQLmcStBp6zxduzEbOG; 1P_JAR=2023-01-25-10; __Secure-3PSIDCC=AIKkIs3zFB8Qc0Oo3-AzH4hzyJkZFsjp0ZEMsrezMMUBxtGeayEzfxjxwSaygz9LHj3OTAhrEdFL
origin: null
referer: http://localhost:3000/
sec-ch-ua: "Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
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/109.0.0.0 Safari/537.36
google api credentials urls
CORS can be a bit fiddly to setup, and errors like this are pretty common. There is a good CORS primer available here.
What is happening in the background is that the API is taking the contents of the origin header, and trying to match it with what is enabled in the credential URLs.
However, if you look at the request headers that are sent, the origin is set as null, which isn't matching your list. Adding null to your configuration should get things working.
Nota bene: it looks like this is a work around for a dev environment, make a note to back it out when you get to prod ;)

Express + Passport session works in Postman but not in browser

I have a node js server running on http://localhost:9000
and a client with react js running on http://localhost:3000
I am able to authenticate user by making a post request in endpoint http:localhost:9000/api/v1/authenticate and send a cookie to client as you can see on my response header
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Connection: keep-alive
Content-Length: 51
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
Content-Type: application/json; charset=utf-8
Date: Fri, 25 Dec 2020 14:03:48 GMT
ETag: W/"33-tyk8lJX6mfHZ8N08Hj//Q3TUtmY"
Expect-CT: max-age=0
Referrer-Policy: no-referrer
Set-Cookie: connect.sid=s%3ALVe2uJLDGv502_M70nCSfjfawWhXG0Zx.zDCxMUAJE54wKO0ecJogSPLWZIQoOdHqF387XEX1A7E; Path=/; Expires=Fri, 08 Jan 2021 14:03:48 GMT; HttpOnly
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
And now after I logged in and check if user is authenticated /check-session,
I am able to get the data in POSTMAN and req.session.passport data exist.
But am not able to get the same result when I make a request in frontend with axios
export const checkAuthSession = async () => {
try {
const req = await axios({
method: 'GET',
url: '/check-session',
withCredentials: true,
});
return Promise.resolve(req.data);
} catch (e) {
return Promise.reject(e);
}
}
I expect to get 200 status and get the data after login in frontend but I get the 404.
These are the request and response header after I make the request with axios:
Request Header
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Cookie: connect.sid=s%3Ag7erGfrj2XWv5jrFXrSk4kJH-qvuCCa7.8e2cnCs1dduo86Ydne1sPDRSoAlYwdiAbGcZJqluZgc
Host: localhost:9000
Origin: http://localhost:3000
Referer: http://localhost:3000/
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/87.0.4280.88 Safari/537.36 Edg/87.0.664.66
Response Header
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Connection: keep-alive
Content-Length: 9
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
Content-Type: text/plain; charset=utf-8
Date: Fri, 25 Dec 2020 14:17:18 GMT
ETag: W/"9-0gXL1ngzMqISxa6S1zx3F4wtLyg"
Expect-CT: max-age=0
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
And this is how I configured CORS in express:
app.use(cors({
origin: 'http://localhost:3000',
credentials: true
}));
Finally found the answer:
In my axios request, I was only setting the withCredentials: true options in my /check-session endpoint.
To fix it, I must set the credentials for all request.
axios.defaults.withCredentials = true;
As MDN also said:
For a CORS request with credentials, in order for browsers to expose the response to frontend JavaScript code, both the server (using the Access-Control-Allow-Credentials header) and the client (by setting the credentials mode for the XHR, Fetch, or Ajax request) must indicate that they’re opting in to including credentials.

Angular 8 Express Post Throws a CORs Error

Yes I know you can normally fix these by setting the origin wilcard to '*' but I'm using "credentials : true", so that's thrown my normal solution out the window.
The Issue I'm having is that when I try to perform a post request to Express, it seems to first submit as an OPTIONS, then get redirected as GET, then redirected again as POST.
All my "Access-Control-Allow-XXXX" headers appear in the original OPTIONS but then gets lost in the redirects.
The error being shown from the browser is;
Access to XMLHttpRequest at 'http://localhost:4200/' (redirected from 'http://localhost:3000/api/save') from origin 'null' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my express cors setup, the dynamic origin was set because I thought the direct might have been looking for the API address as a possible origin, and then undefined and null because I got annoyed with it;
var app = express();
var port = process.env.PORT || 3000;
whitelist = [UI_BASE_URL, API_BASE_URL, undefined, null];
app.use(
cors({
allowedHeaders: [
'Origin',
'X-Requested-With',
'Content-Type',
'Accept',
'X-Access-Token',
'Access-Control-Allow-Origin',
'Access-Control-Allow-Headers',
'Access-Control-Allow-Methods'
],
preflightContinue: false,
credentials: true,
origin: function(origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
})
);
And here's the service call from angular
const httpOptions = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
}),
};
save(myData): Observable<any> {
return this.http.post(
this.workSpaceReportURL + 'save',
{
data: myData,
withCredentials: true,
},
httpOptions
);
}
and because they might be useful, the request and response headers from the POST.
RESPONSE
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate
Connection: keep-alive
Content-Length: 43
Content-Type: text/plain; charset=utf-8
Date: Mon, 11 Nov 2019 14:50:31 GMT
Expires: 0
Location: http://localhost:4200
Pragma: no-cache
Set-Cookie: connect.sid=s%3Aj3wYyE_I14o6b_C-L6EDnOxesW0CBVks.WEwBNiQegZ1ufG2d40%2BF4BGfbCWPbOz9FS4Kj%2BC14Pc; Path=/; Expires=Mon, 18 Nov 2019 13:30:31 GMT; HttpOnly
Strict-Transport-Security: max-age=15552000; includeSubDomains
Surrogate-Control: no-store
Vary: Origin, Accept
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 184
Content-Type: application/json
Host: localhost:3000
Origin: http://localhost:4200
Referer: http://localhost:4200/data-controller
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/78.0.3904.97 Safari/537.36
I've tried a number of different solutions I've come across on SO but they normally end up being fixed by the usual wildcard origin.
Thanks for any suggestions you can make.
It looks like you used an old way to add cord headers. Have you tried doing this?
var cors = require('cors')
app.use(cors())
Make sure to run the last one before you run your other app.use
Ok, I think I realised what the solution was. I'd just spent so long starting at it to realise.
I'd managed to strip out the Content-Type without noticing, and was passing the withCredentials in as part of the body, not the httpOptions (which I tihnk was my original problem).
In case it helps someone else out a few years from now, the httpOptions and post should've looked like the below.
I'm now going to go stand in the server room of shame.
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
}),
withCredentials: true,
};
save(myData): Observable<any> {
return this.http.post(
this.workSpaceReportURL + 'save',
{
myData,
},
httpOptions
);
}

Custom cookie sent to browser but not stored

I've tried multiple configuration and read multiple posts about this issue but I'm still lost.
The custom cookie sent by my api server is received by the browser but never stored. And I can't figure out why.
I developed a node/express api server deployed on heroku.
My front-end uses Vuejs and is deployed on firebase.
Here are the code related to my cookie configuration :
SERVER-SIDE
Cors
app.use(
cors({
origin: 'https://my-app.firebaseapp.com',
credentials: true,
exposedHeaders: ['customCookie']
})
);
Set-cookie
const cookieOptions = {
httpOnly: true,
sameSite: 'None',
expires: expirationDate,
secure: true,
path: '/',
domain: 'https://my-app.firebaseapp.com',
};
res.cookie('customCookie', 'value', cookieOptions)
CLIENT-SIDE
Axios
axios.defaults.baseURL = 'https://my-app.herokuapp.com';
axios.defaults.withCredentials = true;
REQUEST HEADER
POST /auth/sign-in HTTP/1.1
Host: my-app.herokuapp.com
Connection: keep-alive
Content-Length: 55
Pragma: no-cache
Cache-Control: no-cache
Origin: https://my-app.firebaseapp.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3921.0 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: */*
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://my-app.firebaseapp.com/auth/sign-in
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,nl;q=0.6,la;q=0.5
RESPONSE HEADER
HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
X-Dns-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Access-Control-Allow-Origin: https://my-app.firebaseapp.com
Vary: Origin, Accept-Encoding
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: customCookie
Set-Cookie: customCookie=value; Domain=https://my-app.firebaseapp.com; Path=/; Expires=Sun, 17 Nov 2019 11:54:30 GMT; HttpOnly; Secure; SameSite=None
Content-Type: application/json; charset=utf-8
Content-Length: 200
Etag: W/"c8-qlzfwyZ+uJQMQIeJOQnFSQYPR6o"
Date: Sun, 20 Oct 2019 11:54:30 GMT
Via: 1.1 vegur
So, the cookie is correctly sent and received here:
Set-Cookie: customCookie=value; Domain=https://my-app.firebaseapp.com; Path=/; Expires=Sun, 17 Nov 2019 11:54:30 GMT; HttpOnly; Secure; SameSite=None
But when I check the tab : Google Dev Tools >> Application >> Cookies >> my-app...
=> There is no cookie stored and therefore the cookie is not sent on subsequent request...
Any idea/advice ?
Thank you very much for your help,
Romain
I think you need to handle Access-Control.
you can do it by adding this code
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
Also, I suppose that you are using Chrome as a browser, can you run chrome without security
by doing this and then check if your cookies stored or not
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
--user-data-dir="C:/Chrome dev session" --args --disable-web-security
I think I get it.
In Chrome (and maybe other navigator), cookies seems to be stored only in the domain address and the domain address, in my case, should be the server app (my-app.herokuapp.com), not the client one (my-app.firebaseapp.com).
In other words, I thought my cookie would be stored and visible in my client-app address but they are actually stored and visible on my domain address.
Now everything works...

CORS cookies not setting by browser , cookies are present in response

I am sending http request to API endpoint of node.js server, this response is containing cookies and showing in mozilla debugger. I am sending this request through localhost.org or by my virtual host e.g myapp.example.com.
I tried AJAX XMLHTTPRequest and angular http as well
also add xhrFields: {withCredentials: true} for AJAX
credentials: 'include' for fetch, etc.
But cookies are not being set by browser, I am trying this for 2 days but this problem is not yet resolved.
this is util function which send ajax request
function sendServerRequest(url,method,data) {
return new Promise(function ( resolve ) {
resolve($.ajax({
url,
method: method || 'GET',
data,
xhrFields: {withCredentials: true},
crossDomain: true,
success: function ( data ) {
return data
},
error: function ( err ) {
try {
let responseStatus = err.responseJSON
if ( responseStatus.status === sessionExpires ) {
sessionExpireCall(responseStatus.message)
}
} catch ( e ) {
console.log('Failed to get response');
}
}
}));
})
}
Response Raw
HTTP/1.1 200 OK
X-RateLimit-Limit: 13000
X-RateLimit-Remaining: 12996
Date: 2019-06-26 06:17:56
X-RateLimit-Reset: 1561533343
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Access-Control-Allow-Origin: http://192.168.10.3
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type,
Authorization
Access-Control-Allow-Credentials: true
set-cookie: true
set-cookie: driverId=c81e728d9d4c2f636f067f89cc14862c; Max-Age=3600;
Domain=192.168.10.3; Path=/; Expires=Wed, 26 Jun 2019 07:17:56 GMT
set-cookie: driverName=kamran; Max-Age=3600; Domain=192.168.10.3; Path=/;
Expires=Wed, 26 Jun 2019 07:17:56 GMT
set-cookie: connect.sid=s%3AX- syECgzpFEZhh4d5B_xfStUoYPrO3p1.%2FPj%2BMo7UnaZto6OGoP%2BOjdKvrJ%2F3Fm%2Bn1BJ%2FXU7Qdh8; Domain=192.168.10.3; Path=/; Expires=Wed, 26 Jun 2019 07:17:56 GMT; HttpOnly
Content-Type: application/json; charset=utf-8
Content-Length: 34
ETag: W/"22-tpsDmOyD3m/F84/JvyRCwDCbeY8"
Connection: keep-alive
{"detail":"verified","status":200}
Request Raw
GET http://localhost:3000/driverboard/verifycode?
mobile=923002222222&vcode=2609 HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Accept: */*
Origin: http://192.168.10.3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Referer: http://192.168.10.3/capptin-driverboard/verification.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: true
CORS is not about cookies, CORS about HTTP headers. It allows making cross-domain requests(from one domain to another. For example from myapp.example.com to google.com). Cookies only send to the same domain, for example from myapp.example.com you can send cookies to the same domain .example.com
Docs here https://developer.mozilla.org/ru/docs/Web/HTTP/CORS
You can Append the cookie to your response with "/" as path.
add cookie in c# core. Append it to response:
context.Response.Cookies.Append(cookieNameAsString, cookieValue, new CookieOptions()
{
Expires = time,
Path = "/",
});
or create a cookie in javascript:
document.cookie = "cookieNameAsString='cookieValue'; max-age=time;";

Resources