Cross domain axios call to pass cookies - express

I have a webapp hosted in heroku under https://xyz.herokuapp.com. I've made it so that when user hits https://xyz.herokuapp.com, it would drop a cookie under the domain "xyz.herokuapp.com".
This is the snippet I have on server side hosted in heroku that sets the cookie.
res.cookie('sample_cookie',randomNumber, {
maxAge: 900000,
httpOnly: true,
sameSite: 'none',
secure: true
});
Further I have CORS configured like so
app.use(cors({
origin: '*'
}));
Now I am building another web app hosted in say abc.netlify.com. Here I have a simple react app that uses axios to call an endpoint under xyz.herokuapp.com. Under this case, I expect during the GET call that goes out to xyz.herokuapp.com from abc.netlify.com, the cookies set by xyz.herokuapp.com to be passed along. But I am not sure how to achieve this.
Here is my axios call made from abc.netlify
axios.get('https://xyz.herokuapp.com/getInfo', {crossDomain:true});
How can I make sure the cookies set under xyz.herokuapp.com gets passed even when the request comes from cross domain like this example. Thanks for your help.

Related

Problem with setting cookies on localhost during development

I have nodejs express app as backend, and vue app as frontend on my server. I use session cookies for authentication and i just can't get them working on my local dev machine. Cookie is sent in the response but it is not saved by browser. I know that problem is that request origin must be same as host and i have read all the articles/questions related to the issue and i just can't solve it.
On the server, everything is proxied with nginx on https. Cookie is set there and everything works fine, because they are on same host.
My local vite dev server is running on https, on port 5173.
I use axios for api calls and i have set
axios.defaults.withCredentials = true;
Cookie properties are
sameSite:'none',
secure:true,
httpOnly:true,
In express:
app.use(
cors({
origin: ['https://localhost:5173', 'https://my.site.com'],
credentials: true,
})
);
Like i said before, cookie is sent in the response from the server and just not stored on browser because in request header:
host:my.site.com
origin:https://localhost:5173
referer:https://localhost:5173/
How can i solve this?
I followed solution in comments on https://stackoverflow.com/a/46412839/13781306.
It partialy works when i set
sameSite:'none',
secure:false,
Cookie is passed in requests but it is not stored in the browser storage/cookies. Which is fine and solves my issue.

ExpressJs: Browser not sending cookies set for another domain set by api server

I have an admin dashboard react app that's running on admin.localhost.com:3000. I have an api server that's running on www.localhost.com:1337, and we have one react app for all clients, but each client uses it on a subdomain, for example, abc.localhost.com:4200, bcd.localhost.com:4200.
So from my admin dashboard I'm trying to log into abc as a client. The api server, when requested, verifies the admin, sets the cookie in the response for abc.localhost.com:4200 and responds with link for the client https://abc.localhost.com/home. The browser code passes the link to window.open().
However, if I check the browser tab for https:abc.localhost.com:4200, I don't see the cookie, so obviously the authentication fails.
res.cookie('token', token, {
secure: true,
domain: `abc.localhost.com:4200`,
sameSite: 'Lax',
maxAge: moment()
.add(10, 'minutes')
.valueOf(),
})
withCredentials is enabled for the client side agent, and the api server is configured accordingly.
It can't be done, server running on www.localhost.com:1337 can't set cookies for abc.localhost.com:4200. Allowing that would be apocalyptic.

Can someone explain what I need to do to places that redirect to "localhost" when deploying the backend of an app

For example I have a middleware in express.js like this
app.use(cors({
origin: "http://localhost:3000",
credentials: true
}))
If I hosted the frontend on for example firebase, the localhost:3000 part would no longer work so what do I need to do?

Is it possible to set an HttpOnly Cookie from one domain to another subdomain

I originally posted this question here: https://security.stackexchange.com/questions/255737/is-it-possible-to-set-an-httponly-cookie-from-one-domain-to-another-subdomain
Please keep in mind that this question is specific to cookies with the HttpOnly flag set to true.
I am pretty sure that the answer to my question is no, but I have been have a hard time finding an answer through official documentation or other posts here. Here is simple use case for some context:
Python backend web application (api.domain.com)
Frontend JavaScript SPA (app.domain.com)
post requests to api.domain.com/api/auth/login/ made from app.domain.com using axios with the correct username and password return a response with an access JWT token in the body and the response sets a refresh cookie with an HttpOnly flag [should fail, since I believe that the cookie cannot be set on app.domain.com from an API request to api.domain.com? -- this is my question]
the access token is stored in memory and passed with each API request
requests made to api.domain.com/api/auth/refresh/ are sent on a schedule to refresh the short-lived access token.
I typically host the frontend app and backend app on the same subdomain (app.domain.com) and do path-based routing with something like CloudFront or nginx, and this works well. For example, all requests starting with /api/* are sent to the backend, and all other requests are sent to the frontend app. Trying to use a separate subdomain for the API seems to fail no matter what options I use for setting the cookie on the server.
Can someone help me confirm that it is in fact not possible to set an HttpOnly cookie on a subdomain like app.domain.com from an API request hosted on api.domain.com? It would be great if anyone can also help me find where this could possibly be found in official documentation.
Searching for set httpOnly cookie across subdomains, I haven't found anything directly relevant. I also didn't find anything in these resources that directly answers my question:
https://owasp.org/www-community/HttpOnly
https://learn.microsoft.com/en-us/previous-versions//ms533046(v=vs.85)?redirectedfrom=MSDN
This is possible. In fact I just did it.
On your frontend, using Axios:
const baseURL = 'https://api.example.com';
const api = axios.create({
baseURL,
withCredentials: true,
});
On your backend, using Express:
app.use(
cors({
origin: 'https://www.example.com',
credentials: true,
}),
);
app.post('/login', async (req, res) => {
res.cookie('someCookie', someCookieValue, {
secure: true,
domain: 'example.com',
httpOnly: true,
});
});

Shared API with Separate Sessions

I have an API & React app running under localhost:4000 (app A) and I want to access app A's API from a second React app localhost:3000 (app B). I configured CORS correctly to allow app B to send requests to app A with credentials.
However, it appears that app A and app B are sharing cookies, that is if I log in on app A, I will be also logged in on app B. Most of the time this is what you want and I have seen many questions along the lines of "How do I share cookies cross-domain". My question is different because I want to not share cookies cross-domain, I would like each domain to have their own set of cookies.
Is this possible?
I'm using express cors and my configuration for the API on app A looks like the following:
app.use(cors({
origin: 'http://localhost:4000',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
credentials: true
}))
My requests from app B (localhost:3000) look like the following:
const transport = axios.create({
withCredentials: true,
headers: { Pragma: 'no-cache' }, //prevent IE11 cacheing
})
transport.get('http://localhost:4000/api/user')
Again app B has access to app A's cookies within the same browser, which is not what I want. Any help would be appreciated :)
If both APIs are using the same cookie mechanism (express cookie-session), you might want to use separate cookie names in each application.
For example:
// in app A
app.use(cookieSession({
name: 'sessionA',
}))
// in app B
app.use(cookieSession({
name: 'sessionB',
}))
In this example, App A could read B's cookies (and vice versa), but they would be stored separately. If you need the cookie to be protected from reading via the other app, you may want to explore using a different secret for each app's cookie configuration as well. These docs explain the keys and secret options.
Or if using express-session:
https://github.com/expressjs/session#name
Note if you have multiple apps running on the same hostname (this is just the name, i.e. localhost or 127.0.0.1; different schemes and ports do not name a different hostname), then you need to separate the session cookies from each other. The simplest method is to simply set different names per app.